"... выполнимо в Python / joblib
..."
Нет проблем с концептуальным замыслом, еще ...
"... Я намерен сделать более эффективным ..."
это самая сложная часть истории.
Почему?
Микрооперация процессора NOP
(ничего не делать ) занимает ~ 0.1 [ns]
в 2020 / 2H.
Микрооперации ЦП занимают примерно ~ 0.3 [ns]
ADD/SUB,
~ 10 [ns]
DIV
в 2020 / 2H.
ЦП может иметь более одного ядра, а архитектуры CIS C могут управлять парой аппаратных потоков на каждом из таких ядер ЦП.
ЦП может развиваться, будет развиваться, но не будет делать никаких магических c чехарда "прыжков" за пределы реальности ограничений, введенных в игру l aws физикой. Никогда.
Планировщик O / S может запланировать CPU для чередования гораздо большего количества программных потоков (потоков исполнения кода), поскольку это чередование выполнения кода генерирует для нас, медленное, с визуальным отображением коры головного мозга примерно 25 Гц. понимание выборки, использование не более чем одного (голосового) или двуручного «устройства» ввода, иллюзия многозадачной операционной системы, но всей такой работы достаточно (нет гарантий для работы не в реальном времени (HRT) systems) помещены в несколько пар потоков CPU-core.
CPU может обеспечить наиболее эффективную обработку, если вычислительные задачи не чередуются сильно. Чем меньше, тем лучше.
ЦП будет в такой "компактной" оркестровке рабочего потока оставаться в пределах примерно ~ 0.3 ~ 10 [ns]
на uop (аппаратная машинная инструкция ЦП) и будет лучше вычислять, если не будет никуда обращаться за данными но в свои собственные аппаратные регистры (выборка данных из кэша L1 «стоит» ~ 0.5 [ns]
, тогда как L2 ~ 8x
дороже, L3 ~ 40x
дороже а ОЗУ может go где угодно от ~70 .. 3++ [ns]
для выборки данных). Таким образом, выполнение чередующихся процессов сопряжено с большими накладными расходами только для восстановления данных, многократно предварительно извлеченных из дорогостоящей ОЗУ, в менее дорогие кэш-память L3, L2 и L1 (просто возмещая затраты в размере ~ 300 ~ 350 [ns]
каждый раз часть данных должна быть получена повторно, поскольку выполнение чередующегося процесса не сохраняет предварительно выбранные данные после того, как планировщик удалил этот поток из ядра процессора, чтобы освободить пространство-время для выполнения другого потока в очереди планировщика).
ЦП может делать все возможное, если не дожидается данных из ОЗУ (каналы памяти и узкие места ввода-вывода известны HP C -efficiency / Враги из-за нехватки ресурсов процессора ).
Этих аппаратных накладных расходов недостаточно «достаточно» , вам придется заплатить намного больше:
Python / joblib.Parallel()delayed()
конструктор тривиально набирать, не так для точной настройки производительности для достижения максимальной эффективности.
Использование значения по умолчанию njobs
(или любой простой ручной настройки) может и чаще всего снижает фактическая эффективность способа обработки в пределах производительности CPU-оборудования.
Существуют ненулевые дополнительные затраты , которые порождены joblib
процессами должен заплатить. Во всех случаях они оплачивают дополнительные затраты на аппаратное обеспечение ЦП за каждый элемент данных, повторно извлеченный из ОЗУ в (теперь планировщик O / S повторно выбран) кэш L3 / L2 / L1 ядра ЦП (эти ~ 3++ [ns]
сотни наносекунд), плюс он "разделяет" слабо приоритетную долю времени выполнения кода ядра ЦП (подробные сведения о настройках максимальной производительности / эффективности см. в параметризации O / S и свойствах планировщика)
и
последнее, но не менее важное
существуют огромные (в масштабе ~ hundreds of [us] if not [ms]
) дополнительные затраты на создание экземпляра процесса, параметры подписи вызовов между процессами ' передача (считайте затраты SER / DES (часто pickle.dumps() / pickle.loads()
) на преобразование данных параметров + Процесс-2-Процесс обмена сжатыми данными ... (время, время, время ...) ... , обратная передача данных результатов процесса (если есть), то есть снова SER / DES-конвейер + P2P-коммуникация ... (время, время, время ... ) ... плюс дополнительные затраты на завершение процесса.
Выполнение всего этого в любом месте, близком к пределу максимальной производительности аппаратного обеспечения ЦП, - это всегда сложно , больше в расслабленной и разнообразной экосистеме, где Python -GIL-lock ограниченное выполнение кода + joblib.Parallel()
-процессы + Cython-ised модули (где вам не нужно комфортно контролировать / настраивать фактическое количество их порожденных под -процессы, не так ли?) сосуществуют, и это уже «эффективность» -tuning wild mix разрешается работать внутри обычного, ориентированного на пользователя MMI уровня COTS O / S.
Если все вышеперечисленное было легко "проглотить" , дополнительные затраты на совместное использование будут следующими:
Пока существуют протоколы с общими переменными, я примет все необходимые меры, чтобы не платить огромную надстройку для выполнения кода n затраты на их «использование».
Кто будет платить огромные расходы, чтобы «арендовать» Rolls-Royce только для ленивой поездки в школу в 9:00 утра и для возвращения иногда ближе к вечеру? выполнимая, но чрезвычайно дорогая «стратегия» . Есть надежные способы избежать общих переменных, и нулевое совместное использование является обязательным для любого программного обеспечения HP C, которое стремится к максимальной производительности с учетом эффективности.
«Я работаю над проектом ...»
Оплата счета только после XY-[man*months]
затраченных усилий может быть слишком поздно:
Проанализировать обработку -стратегия и все фактические надстройки априори стоят решения.
Поздние сюрпризы - самые дорогие.
Даже оригинал, накладные расходы- Наивность и атомарность работы, игнорирующая закон Амдала , показывает, что существует главный предел - закон убывающей отдачи, который вы никогда не сможете обойти. И это были дополнительные затраты без учета optimisti c модели.
Реальность работает против вашей воли, чтобы получить улучшенная производительность. Тем более, что дополнительные затраты на макросопи c (связанные с многопроцессорной обработкой) возьмут (и очень скоро станут) доминирующее положение. Добавление протоколов обмена данными с совместно используемыми переменными снижает эффективность на много порядков (не только ~2
затраты на задержку добавляются для повторной выборки из кэша / ОЗУ, но и затраты на межпроцессную повторную синхронизацию «блокируют» свободный поток наиболее эффективной обработки на базе ядра ЦП, поскольку зависимости от других процессов, не связанных с ядром ЦП, вызывают состояния блокировки, похожие на барьеры, когда состояние совместно используемой переменной проверяется / повторно распространяется, чтобы поддерживать общесистемную согласованность ... ценой потери времени и эффективности превратится в крушение havo c ... только для простоты синтаксического сахара Python разделяемой переменной "комфорта" .
Возможно, вы захотите прочитать подробнее об этом,
возможно, с примерами кода:
Если вас интересует дальнейшее чтение joblib
& изменено - Закон Амдала влияет на , не стесняйтесь погружаться. Дьявол скрыт в деталях. Как всегда.