У меня есть реализация универсальной матрицы, и я создаю опцию
использовать операторы ‘*’ и ‘+’ с параллельной обработкой и последовательной обработкой.
пример параллельных вычислений:
рассмотрим, что у нас есть матрицы m1 и m2 и m3 = m1 * m2.
мы вычисляем м3 строку i ‘с разными потоками.
плюс:
последовательный расчет просто рассчитать м3 [0,0], м3 [0,1] .. и т. д.
Чем я измерял время каждой операции, используя на больших и малых матрицах
и я заметил, что на маленьких матрицах последовательная обработка была быстрее, чем параллельная обработка, но с другой стороны параллельная обработка имела лучшие показатели на больших матрицах.
The results:
+----------------------------+--------------------------------+------------+
| Big | Small | |
+----------------------------+--------------------------------+------------+
| * | + | * | + | |
+-------------+--------------+---------------+----------------+------------+
| 0.697798sec | 0.0407585sec | 8.7408e-05sec | 0.000109052sec | Parallel |
+-------------+--------------+---------------+----------------+------------+
| 11.9984sec | 0.0235058sec | 6.68e-07sec | 7.76e-07sec | Serial |
+-------------+--------------+---------------+----------------+------------+
Может кто-нибудь объяснить, почему?
Большое спасибо!
Например, в небольшой матрице, например матрице размером 10 * 10, последовательная обработка выгодна, потому что программу не нужно разбивать на более мелкие части, а затем переносить на последовательный или одиночный процессор для дальнейшей обработки.
Когда эта же матрица 10 * 10 обрабатывается посредством параллельной обработки, она будет разбита на более мелкие части, которые затем будут поданы на каждый из отдельных процессоров (имейте в виду, все это разбивает матрицу и передает ее каждому параллельных процессоров требует времени) и, следовательно, производительность параллельной обработки уменьшается по сравнению с небольшими матрицами.
В случае если большая матрица, например, матрица размером 100 * 100, передается последовательному процессору, процессор не может обработать эту единственную программу, но должен обрабатывать все прерывания, все остальные процессы и, следовательно, ждать время увеличивается в этом случае. Но когда одна и та же матрица 100 * 1000 передается для параллельной обработки, она разбивается на достаточно маленькие кусочки и обрабатывается, возможно, несколькими процессорами. Например, если процессор содержит два ядра / процессора, он может выделить одно для этой матрицы, а другой — для всех остальных обработчиков прерываний и других программ, поэтому время ожидания значительно сократится со временем.
Есть много факторов в производительности с несколькими потоками или задачами.
накладные расходы
Независимо от того, есть у вас ОС или нет, параллельное программирование сопряжено с накладными расходами. Как минимум, другой процессор (ядро) должен быть настроен для выполнения ядра потока. Это занимает время выполнения.
Другим пунктом является время ожидания синхронизации. В какой-то момент первичный процессор должен дождаться завершения работы других процессоров.
Существует также накладные расходы, связанные с сигнализацией или связью. Вторичный процессор (ы) должен занять время выполнения, чтобы уведомить основной процессор, что вычисления завершены, и они должны где-то хранить результаты.
Если накладные расходы в вашем потоке занимают больше времени, чем время выполнения потока (например, простое одиночное умножение), вы можете не заметить какой-либо экономии времени из-за параллельных усилий.
Нагрузка
Объем работ, выполняемых потоками, должен быть значительным. Матрице 10х10 может не хватить работы, чтобы преодолеть накладные расходы. При создании потоков они должны выполнять больше работы, чтобы оправдать накладные расходы на их создание и мониторинг.
Делегация
Если есть ОС, ОС отвечает за то, как будут выполняться потоки. Они могут выполняться в циклическом стиле на одном процессоре, даже если в системе несколько процессоров. (ОС может делегировать одну задачу или приложение на процессор). Не будет большого улучшения производительности, когда ОС делит ваши потоки на одном ядре. Возможно, вы захотите исследовать ОС, чтобы выяснить, можете ли вы принудительно делегировать код вашего потока другим ядрам.
Столкновения памяти
Большинство многопроцессорных платформ разделяют память. Аппаратное обеспечение может иметь только одну шину данных между процессорами и памятью. Таким образом, одному процессору придется ждать, пока другой обращается к памяти (поскольку только один процессор может одновременно использовать шину данных). Это может замедлить эффективность вашей программы, так что ваши результаты производительности будут незначительными.
Кэши данных и конвейеры инструкций
Если ваша программа не оптимизирована для кэширования данных, создание нескольких потоков не приведет к значительному повышению производительности. Процессор может тратить время, тратя время на перезагрузку своего кеша из памяти (особенно, когда процессоры opter заканчивают использовать шину данных). Возможно, вы сможете добиться большего улучшения в одном потоке выполнения, разработав свои данные и обрабатывая их вокруг структуры кэша данных.
Процессоры также могут иметь кеши или конвейеры для инструкций. Передачи в исполнении программы раздражают процессор. Он должен тратить время на проверку того, находится ли код в кеше или чтобы получить и получить код. Сокращение числа передач выполнения ускорит вашу программу, обычно больше, чем создание потоков.
Ваши результаты могут быть незначительными из-за различных факторов, особенно если ваша платформа выполняет другие приложения, в то время как ваша работает. Изучите методы для сравнительного анализа. Вам может понадобиться либо иметь значительный объем данных, либо запустить свою программу значительное количество времени (или оба). Обычно значительными являются итерации 1E09 в области эталонных тестов (многие компьютеры могут выполнять инструкции за 1E-8 секунд, поэтому вам придется запускаться много раз, чтобы получить хорошее среднее значение).