Почему мой сценарий Perl для распаковки файлов медленнее, когда я использую потоки? - PullRequest
3 голосов
/ 09 ноября 2009

Итак, я запускаю Perl 5.10 на Core 2 Duo MacBook Pro, скомпилированном с поддержкой потоков: usethreads=define, useithreads=define. У меня есть простой скрипт для чтения 4-х сжатых файлов, содержащих по 750000 строк каждый. Я использую Compress :: Zlib для распаковки и чтения файлов. У меня есть 2 реализации, единственная разница между ними в том, что одна включает use threads. Кроме этого оба сценария запускают одну и ту же подпрограмму для чтения. Следовательно, в psuedocode программа без многопоточности делает это:

read_gzipped(file1);
read_gzipped(file2);
read_gzipped(file3);
read_gzipped(file4);

Версия с резьбой выглядит так:

my thr0 = threads->new(\$read_gzipped,'file1')
my thr1 = threads->new(\$read_gzipped,'file1')
my thr2 = threads->new(\$read_gzipped,'file1')
my thr3 = threads->new(\$read_gzipped,'file1')

thr0->join()
thr1->join()
thr2->join()
thr3->join()

Теперь многопоточная версия фактически работает почти в 2 раза медленнее, чем не поточный сценарий. Это явно не тот результат, на который я надеялся. Кто-нибудь может объяснить, что я здесь делаю не так?

Ответы [ 4 ]

10 голосов
/ 09 ноября 2009

Вы используете потоки, чтобы попытаться ускорить то, что связано с IO, а не с процессором. Это только приводит к большему количеству конфликтов ввода-вывода, что замедляет работу сценария.

9 голосов
/ 09 ноября 2009

Я предполагаю, что узким местом для операций GZIP является доступ к диску. Если у вас есть четыре потока, конкурирующих за доступ к диску на жестком диске, это значительно замедляет процесс. Головка диска должна будет быстро переходить к разным файлам. Если вы обрабатываете только один файл за раз, заголовок может оставаться рядом с этим файлом, и кэш диска будет более точным.

4 голосов
/ 09 ноября 2009

ithreads работают хорошо, если вы имеете дело с чем-то, что в основном не процессор. декомпрессия связана с процессором.

Вы можете легко решить проблему с помощью модуля Parallel :: ForkManager .

Вообще - темы в Perl и не очень хорошие.

0 голосов
/ 10 ноября 2009

Я не готов предположить, что вы связаны с вводом / выводом, не увидев вывод top во время работы. Как и в случае с depesz, я склонен полагать, что операции сжатия / распаковки (которые математически сложны) с большей вероятностью будут связаны с процессором.

Когда вы имеете дело с операцией, связанной с ЦП, использование большего количества потоков / процессов, чем у вас процессоров, почти никогда [1] не улучшит ситуацию - если загрузка ЦП уже на 100%, больше потоки / процессы не будут магически увеличивать свою емкость - и, скорее всего, ухудшат ситуацию, добавив дополнительные издержки на переключение контекста.

[1] Я слышал, что для сложных компиляций, таких как сборка нового ядра, полезно make использовать вдвое больше процессов, чем у машины с процессорами, и мой личный опыт показывает, что это быть точным Объяснение, которое я слышал для этого, состоит в том, что это позволяет каждому ЦПУ быть занятым, компилируя в одном процессе, в то время как другой процесс ожидает выборки данных из основной памяти. Если вы рассматриваете компиляцию как процесс, связанный с процессором, это исключение из обычного правила. Если вы рассматриваете это как случай ввода-вывода (где ввод-вывод находится между процессором и основной памятью, а не дисковым / сетевым / пользовательским вводом-выводом), это не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...