Создание потока для каждой операции или несколько потоков для различных операций? - PullRequest
2 голосов
/ 16 марта 2012

Для проекта класса я пишу простой матричный множитель в Python. Мой профессор попросил, чтобы это было нарезано. То, как я сейчас это делаю, - это создание потока для каждой строки и добавление результата в другую матрицу.

То, что я хотел знать, будет ли быстрее, если вместо создания потока для каждой строки он создаст некоторое количество потоков, каждый из которых обрабатывает различные строки.

Например: задано Matrix1 100x100 * Matrix2 100x100 (размеры матрицы могут сильно различаться):

  • 4 потока каждая обработка 25 строк
  • 10 потоков каждая обработка 10 строк

Может быть, это проблема тонкой настройки, или, возможно, издержки процесса создания потока все еще быстрее, чем описанный выше механизм распространения.

Ответы [ 2 ]

2 голосов
/ 16 марта 2012

Ни в одном случае задача, связанная с процессором, не будет быстрее в Python в многопоточном режиме.Из-за Global Interpreter Lock , только один поток может быть выполнен сразу (если вы не напишите какое-либо расширение C и не снимите блокировку явно).

Это относится как к стандартной реализации CPython, так и кPyPy.В Jython старайтесь использовать поток на ядро, больше не имеет смысла.

Пожалуйста, ознакомьтесь с большим обзором GIL David Beazley .

С другой стороны, если ваш профессор не возражает, вы можете использовать многопроцессорность .

2 голосов
/ 16 марта 2012

Вероятно, вы получите наилучшую производительность, если будете использовать один поток для каждого ядра ЦП, доступного для машины, на которой работает ваше приложение.Вы не получите никакого выигрыша в производительности, запустив больше потоков, чем у вас есть процессоры.

Если вы планируете порождать новые потоки каждый раз, когда выполняете умножение матриц, тогда очень мало надежды на то, что ваше многопоточное приложение когда-либо превзойдет однопоточную версию, если вы не умножаете действительно огромные матрицы.Издержки, связанные с созданием потока, слишком велики по сравнению со временем, необходимым для умножения матриц.Тем не менее, вы можете получить значительное повышение производительности, если будете запускать все рабочие потоки один раз при запуске процесса, а затем использовать их снова и снова, чтобы выполнить многократное умножение матриц.

Для каждой пары матриц, которые вы хотите умножить, вы захотите загрузить матрицы умножения и умножения в память один раз, а затем разрешить всем вашим рабочим потокам одновременно обращаться к памяти.Это должно быть безопасно, потому что эти матрицы не будут меняться во время умножения.

Вы также должны иметь возможность разрешить всем рабочим потокам одновременно записывать свои выходные данные в одну и ту же выходную матрицу, поскольку (из-за природы матрицыумножение) каждый поток заканчивает тем, что записывает свой вывод в различные элементы матрицы, и не будет никакого конфликта.

Я думаю, что вы должны распределить строки между потоками, поддерживая целое число NextRowToProcess, которое совместно используетсявсе темы.Всякий раз, когда поток готов обработать другую строку, он вызывает InterlockedIncrement (или любую атомарную операцию приращения, доступную на вашей платформе), чтобы безопасно получить следующую строку для обработки.

...