Чому важко надати ефективність під час використання бібліотек?


10

Будь-яка невелика обробка бази даних може бути легко вирішена сценаріями Python / Perl / ..., що використовує бібліотеки та / або навіть утиліти з самої мови. Однак, що стосується продуктивності, люди, як правило, тягнуться до мов C / C ++ / низького рівня. Можливість адаптації коду до потреб, здається, є тим, що робить ці мови настільки привабливими для BigData - будь то управління керуванням пам’яттю, паралелізм, доступ до диска або навіть оптимізація низького рівня (через складання конструкцій на рівні C / C ++).

Звичайно, такий набір переваг не обійдеться без витрат: написання коду, а іноді навіть винахід колеса , може бути досить дорогим / стомлюючим. Хоча доступно багато бібліотек, люди схильні писати код самостійно, коли їм потрібно забезпечити ефективність. Що відключає твердження про ефективність використання бібліотек під час обробки великих баз даних?

Наприклад, розгляньте підприємство, яке постійно сканує веб-сторінки та аналізує зібрані дані. Для кожного розсувного вікна над отриманими даними запускаються різні алгоритми виведення даних. Чому розробники відмовляються від використання наявних бібліотек / фреймворків (будь то для сканування, обробки тексту та пошуку даних)? Використання вже реалізованих матеріалів не тільки полегшить тягар кодування всього процесу, але й заощадить багато часу.

В одному кадрі :

  • що робить написання коду самим собою гарантією виконання?
  • Чому ризикувати покладатися на рамки / бібліотеки, коли ви повинні забезпечити високу продуктивність?

1
Чи можете ви уточнити точне запитання? Можливо, деякі можливі відповіді, які ви маєте на увазі, також можуть допомогти.
Амір Алі Акбарі

@AmirAliAkbari SeanOwen опублікував відповідь, і я помітив відсутність конкретності в моєму запитанні. Я додав коментар до його повідомлення. Будь ласка, не соромтеся запропонувати будь-які вдосконалення в публікації - я планую видалити її, інакше.
Рубенс

Відповіді:


4

Зробивши переписування гри знову і знову (і все ще роблю це), моєю негайною реакцією була адаптованість .

У той час як фреймворки та бібліотеки мають величезний арсенал (можливо взаємозамінних) процедур для стандартних завдань, їх властивість фрейму часто (завжди?) Відключає ярлики. Насправді, більшість фреймворків мають якусь основну інфраструктуру, навколо якої реалізований основний рівень базової функціональності. Більш конкретна функціональність використовує основний шар і розміщується у другому шарі навколо ядра.

Тепер під ярликами я маю на увазі перехід від другого шару до іншого режиму другого шару без використання ядра. Типовим прикладом (з мого домену) можуть бути часові позначки: у вас є якесь джерело даних, що маркується часом. Поки що завдання полягає в тому, щоб просто прочитати дані з дроту і передати їх до основної, щоб ваш інший код міг на ньому бенкетувати.

Тепер ваша галузь дуже добре змінює формат часових позначок за замовчуванням (у моєму випадку вони перейшли від часу Unix до GPS). Якщо ваша рамка не є галузевою, дуже малоймовірно, що вони готові змінити основне уявлення про час, тож ви в кінцевому підсумку використовуєте рамку, яка майже робить те, що ви хочете. Кожен раз, коли ви отримуєте доступ до своїх даних, вам слід спершу перетворювати їх у формат, який відмічається галузевим часом, і кожного разу, коли ви хочете їх змінювати, вам доведеться перетворювати їх назад у те, що ядро ​​вважає за потрібне. Немає можливості передати дані прямо з джерела в раковину без подвійного перетворення.

Тут будуть світитися ваші власноруч виготовлені рамки, це лише незначна зміна, і ви знову моделюєте реальний світ, тоді як всі інші (не галузеві) рамки тепер матимуть недоліки в продуктивності.

З часом невідповідність між реальним світом та моделлю посилиться. З рамками поза-полицею ви скоро зіткнутися такими питаннями , як: Як я можу уявити thisв thatабо як рутинному Xприймати / продукцію Y.

Поки що мова йшла не про C / C ++. Але якщо з якихось причин ви не можете змінити рамку, тобто вам доведеться миритися з подвійним перетворенням даних, щоб переходити з одного кінця на інший, тоді ви зазвичай використовуєте щось, що мінімізує додаткові накладні витрати. У моєму випадку перетворювач TAI-> UTC або UTC-> TAI найкраще залишити на сировину C (або FPGA). Неможлива елегантність, не існує глибокої структури розумних даних, яка робить проблему банальною. Це просто нудне твердження перемикача, а чому б не використовувати мову, компілятори якої добре оптимізують саме це?


1
+1 Можливо, я винен у тому, що я не дуже чітко виклав свою посаду, тому інші раніше цього не розуміли. Це, безумовно, та відповідь, яку я шукав. Дякую.
Рубенс

7

Я не думаю, що всі прагнуть до C / C ++, коли продуктивність є проблемою.

Перевага для написання коду низького рівня полягає у використанні меншої кількості циклів процесора, а іноді і менше пам’яті. Але зауважу, що мови вищого рівня можуть переходити до мов нижчого рівня та робити це, щоб отримати частину цього значення. Мови Python та JVM можуть це зробити.

Науковець, що використовує, наприклад, scikit-learn на своєму робочому столі, вже закликає сильно оптимізовані рідні процедури, щоб зробити число. Немає сенсу писати новий код для швидкості.

У розповсюдженому контексті "великих даних" ви зазвичай є вузьким місцем руху даних: передача мережі та введення-виведення. Рідний код не допомагає. Що допомагає не писати один і той же код для швидшого запуску, а писати розумніший код.

Мови вищого рівня дозволять вам реалізовувати більш складні розподілені алгоритми за певний час розробника, ніж C / C ++. У масштабі, розумніший алгоритм з кращим рухом даних буде бити тупий нативний код.

Також зазвичай вірно, що час розробника та помилки коштують навантаження більше, ніж нове обладнання. Рік часу старшого розробника може бути повністю завантажений у розмірі 200 000 доларів; протягом року, який також орендує сотні серверів, що варті часу на обчислення. У більшості випадків це просто не має сенсу заважати оптимізувати над киданням на нього більшої кількості апаратних засобів.

Я не розумію подальших дій щодо "дозволу" та "відключення" та "затвердження"?


Вибачте за непорозуміння. Мій намір полягав у тому, щоб знайти відповіді про важливість контролю над програмою та про те, як цей контроль послаблюється бібліотеками. Звичайно, ви можете припустити, що про них (люди зазвичай не переписують pthreads), але якщо дані змінюються (навантаження, пропускна здатність, ...), можливо, вам знадобиться отримати доступ до джерела lib, щоб забезпечити продуктивність. І так, це не обов'язково C / C ++ - хоча вони, як правило, мови, обрані для hpc. Чи можу я видалити своє запитання, чи ви хочете змінити його на щось більш конкретне? Я приймаю будь-які пропозиції щодо її вдосконалення.
Рубенс

1
Ні, це тонке запитання, ви можете відобразити свої коментарі тут, редагуючи це питання, якщо вам це подобається.
Шон Оуен

Перевірте, чи питання зараз має сенс. Я додав невеликий випадок, щоб зробити його більш простим. Якщо ви хочете трохи розглянути питання, будь ласка, не соромтесь його відредагувати.
Рубенс

4

Як ми всі знаємо, в цифровому світі існує багато способів виконати ту саму роботу / отримати очікувані результати.

А обов'язки / ризики, що випливають з коду, лежать на плечах розробників.

Це мало, але, мабуть, дуже корисний приклад з .NET світу ..

Тому багато розробників .NET використовують вбудований BinaryReader - BinaryWriter для серіалізації даних для продуктивності / отримання контролю над процесом ..

Це вихідний код CSharp для вбудованого в клас BinaryWriter класу FrameWork 'один із перевантажених методів запису:

// Writes a boolean to this stream. A single byte is written to the stream
// with the value 0 representing false or the value 1 representing true.
// 
public virtual void Write(bool value) 
{
     //_buffer is a byte array which declared in ctor / init codes of the class
    _buffer = ((byte) (value? 1:0));

    //OutStream is the stream instance which BinaryWriter Writes the value(s) into it.
    OutStream.WriteByte(_buffer[0]);
}

Як бачите, цей метод можна записати без додаткового призначення змінної _buffer:

public virtual void Write(bool value) 
{
    OutStream.WriteByte((byte) (value ? 1 : 0));
}

Не призначаючи, ми могли б отримати кілька мілісекунд. Ці кілька мілісекунд можна прийняти як "майже нічого", але що робити, якщо є багатотисячне написання (тобто в серверному процесі)?

Припустимо, що "кілька" - це 2 (мілісекунди), а багатотисячні екземпляри - лише 2.000 .. Це означає, що на 4 секунди більше часу на процес..4 секунди повернення пізніше ..

Якщо ми продовжуємо тематику з .NET і якщо ви можете перевірити вихідні коди BCL - .NET Base Class Library- від MSDN, ви можете побачити чимало зниження продуктивності від розробника.

Будь-яка точка з джерела BCL Це нормально, що ви бачите, що розробник вирішив використовувати цикли while () або foreach (), які могли б реалізувати швидший цикл для () у своєму коді.

Цей невеликий прибуток дає нам загальну продуктивність ..

А якщо ми повернемося до методу BinaryWriter.Write ().

Насправді додаткове присвоєння імплементації _buffer не є виною розробника. Це точно вирішити "залишатися в безпеці"!

Припустимо, що ми вирішили не використовувати _buffer і вирішили застосувати другий метод. Якщо ми спробуємо надсилати багатотисячні байти через провід (тобто завантажувати / завантажувати дані BLOB або CLOB) за допомогою другого методу, це може вийти з ладу, тому що з'єднання втрачено. Тому ми намагаємось надіслати всі дані без будь-яких перевірок та механізму контролю. Коли з'єднання втрачено, і сервер, і клієнт ніколи не знають, чи надсилаються дані завершено чи ні.

Якщо розробник вирішить "залишатися в безпеці", то це, звичайно, означає, що витрати на продуктивність залежать від впровадженого механізму "перебування в безпеці".

Але якщо розробник вирішить "стати ризикованим, набути продуктивності", це теж не помилка. Поки є деякі дискусії щодо "ризикованого" кодування.

І як невеличке зауваження: розробники комерційних бібліотек завжди намагаються бути в безпеці, оскільки вони не можуть знати, де їх код використовуватиме.


4

Виходячи з точки зору програмістів, рамки рідко орієнтуються на ефективність як найвищий пріоритет. Якщо у вашій бібліотеці буде широко використовуватися те, що, швидше за все, цінують люди, це простота використання, гнучкість та надійність.

Продуктивність, як правило, цінується у вторинних конкурсних бібліотеках. "Бібліотека X краще, тому що вона швидша." Навіть тоді дуже часто ці бібліотеки пропонують найоптимальніше рішення, яке може бути широко використане.

Використовуючи будь-які рамки, ви за своєю суттю ризикуєте існувати швидше рішення. Я можу зайти так далеко, щоб сказати, що швидше рішення майже завжди існує.

Написати щось самостійно - це не гарантія ефективності, але якщо ви знаєте, чим займаєтесь і маєте досить обмежений набір вимог, це може допомогти.

Прикладом може бути розбір JSON. Існує сотня бібліотек для різних мов, які перетворять JSON в референтний об'єкт і навпаки. Я знаю про одну реалізацію, яка робить все це в регістрах процесора. Це помірно швидше, ніж усі інші парсери, але воно також дуже обмежене, і обмеження залежатиме від того, з яким процесором ви працюєте.

Чи хороша ідея побудови високоефективного аналізатора JSON для оточення? Я б використовував шановну бібліотеку 99 разів із 100. У цьому окремому екземплярі кілька додаткових циклів процесора, помножених на мільйон ітерацій, зробили б час для розробки потрібним.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.