Насколько распараллеливание помогает производительности, если программа связана с памятью?
Я распараллелил программу на Java. На Mac с 4 ядрами ниже указано время для разного количества потоков.
threads # 1 2 4 8 16
time 2597192200 1915988600 2086557400 2043377000 1931178200
На сервере Linux с двумя сокетами, каждый с 4 ядрами, ниже измеренное время.
threads # 1 2 4 8 16
time 4204436859 2760602109 1850708620 2370905549 2422668438
Как вы видели, ускорение далеко от линейного ускорения. В этом случае почти нет издержек распараллеливания, таких как синхронизация или зависимости ввода / вывода.
У меня есть два вопроса:
- Означают ли эти данные, что эта Java-программа связана с памятью?
- Если да, есть ли способ еще больше улучшить производительность, не меняя аппаратное обеспечение?
2 ответа
Отвечая на заглавный вопрос
Закон Амдала объясняет, что ускорение, полученное при распараллеливании программы, зависит от того, какая часть программы распараллеливается.
И мы также должны добавить накладные расходы для координации параллелизма.
Поэтому мы учитываем, какой процент / части программы распараллеливаемы и какие накладные расходы (синхронизация, обмен данными, ложное совместное использование и т. Д.) Возникают.
Можно ли распараллелить чтение памяти?
С жесткого диска
Вы можете читать с 2 разных жестких дисков одновременно без замедления.
Но обычно параллелизм не обеспечивает ускорения чтения с жесткого диска.
Жесткие диски (то есть диски с вращающимся диском) были оптимизированы для последовательного чтения, а перемещение между областями памяти замедлит общий процесс передачи памяти.
Твердотельные накопители на самом деле достаточно хороши для случайного доступа к данным, скачкообразно перемещаясь по памяти, поэтому с твердотельными накопителями поддержание полной очереди чтения / записи - хорошая идея.
Из оперативки и кеша
Понимание идеи строки кэша поможет избежать ложного обмена.
Этот тип операции с памятью можно эффективно распараллелить, например, выполнить итерацию по массиву, разделив его на четыре раздела.
Ваш вопрос
Я предполагаю, что ваше время указано в наносекундах, поэтому на компьютере 1 программа заняла 2,5 секунды, а затем выровнялась примерно до 2 секунд с пиком в 1,9 секунды.
Я надеюсь, что у вас одновременно работало минимальное количество фоновых программ, и вы несколько раз выполняли эти тесты, чтобы избавиться от ошибок.
Кроме того, нарушения могут возникать по времени из-за компиляции виртуальной машины Java (JIT) Just In Time, поэтому для точного определения времени вы захотите выполнить код в цикле несколько раз и сохранить время последней итерации., (или предварительно скомпилировать в нативный код).
Кроме того, с момента первого запуска программы большая часть данных, использованных с жесткого диска, будет перемещена в кэш, поэтому последующие выполнения должны выполняться быстрее. (Так что либо используйте синхронизацию с последнего запуска после зацикливания, чтобы убедиться, что память находится в кэше, либо используйте первый тайминг, но выключайте и включайте компьютер между таймингами).
Является ли программа Memory Bound?
Сложно сказать, основываясь только на вашем времени.
Первый компьютер занимал 2,5 секунды, затем имел ускорение на 20% с двумя потоками, но затем оставался на уровне около 2,0 секунд.
Само по себе это ускорение могло быть просто результатом того, что JIT и кеш-память заполнялись синхронизацией в 1 потоке. После этого любые различия во времени выполнения могут быть просто шумом.
Второму компьютеру потребовалось 4,2 секунды, затем 2,8, затем 1,9, затем примерно до 2,3 секунд.
Похоже, что это действительно демонстрирует некоторый тип ускорения с параллелизмом, но происходит некоторое время конфликта (память, строки кэша, синхронизация и т. Д.), Что демонстрирует увеличение времени с 4 потоков до 8 потоков.
Есть ли способ улучшить производительность?
Используйте профилировщик для своего кода, определите, какие части кода занимают больше всего времени.
(Вы можете смоделировать профилировщик, отлаживая ваш код и разбивая его, и посмотрите, где находится программа. Повторите это 10 раз, чтобы увидеть, есть ли одна часть, в которой пропорционально больше остановлено, чем другая.)
Используйте лучшие алгоритмы или лучше расположите данные в памяти (структуры данных) для решения проблемы.
Используйте больше параллелизма в проблеме.
Попробуйте сделать так, чтобы память жесткого диска читалась последовательно. Может быть, есть только один поток с чтениями с жесткого диска, а затем помещает данные в параллельную очередь для обработки другими потоками.
Ну, они подразумевают, что алгоритм не связан с процессором. Вероятно, он связан чем-то другим - это может быть память, ввод-вывод или что-то еще, но, скорее всего, он не связан с процессором.