Параллель, но медленнее

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

5
задан blueomega 20 October 2009 в 01:13
поделиться

5 ответов

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

Другая проблема заключается в том, что arrow_area_circle используется совместно между потоками. Если у вас есть поток, работающий на каждом ядре, увеличение arrow_area_circle сделает копию в кешах других ядер недействительной, что приведет к их повторной выборке. arrow_area_circle ++, который должен занять пару циклов, займет десятки или сотни циклов. Попробуйте создать arrow_area_circle для каждого потока и объединить их в конце.

РЕДАКТИРОВАТЬ:

10
ответ дан 18 December 2019 в 07:10
поделиться

Переключение контекста.

2
ответ дан 18 December 2019 в 07:10
поделиться

Похоже, вы используете какой-то компилятор с автоматическим распараллеливанием. Я собираюсь предположить, что в вашей системе более 1 ядра / ЦП (поскольку это было бы слишком очевидно - и отсутствие гиперпоточности на Pentium 4 не считается наличием двух ядер, независимо от того, во что маркетинг Intel может вас поверить. Я вижу две проблемы. Первый тривиален и, вероятно, не ваша проблема:

  1. Если переменная arrow_area_circle совместно используется вашими процессами, то выполнение arrow_area_circle ++ вызовет использование инструкции блокировки для синхронизации значения атомарно надежным способом. Вы должны увеличить «частную» переменную, а затем добавить это значение только один раз в конце к общей переменной arrow_area_circle вместо увеличения arrow_area_circle во внутреннем цикле.

  2. Функция rand () для правильной работы должна внутренне выполняться с критической секцией. Причина в том, что его внутреннее состояние / начальное значение является статической переменной общего доступа; в противном случае два разных процесса могли бы получить один и тот же результат от rand () с необычно высокой вероятностью только потому, что они вызывали rand () почти в одно и то же время. Это означает, что rand () работает медленно, особенно потому, что больше потоков / процессов вызывают его одновременно. В отличие от переменной arrow_area_circle (которой просто нужно атомарное приращение), истинная критическая секция должна быть вызвана функцией rand (), потому что ее обновление состояния более сложное. Чтобы обойти это, вы должны получить исходный код для вашего собственного генератора случайных чисел и использовать его с частным начальным значением или состоянием. Исходный код для стандартной реализации rand () в большинстве компиляторов широко доступен.

Я также хотел бы отметить, что вы используете функцию pow (,) для выполнения того же действия, что и x * x. Последний примерно в 300 раз быстрее первого. Хотя этот момент не имеет отношения к задаваемому вами вопросу. :)

7
ответ дан 18 December 2019 в 07:10
поделиться

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

Что бы вы ни делали, убедитесь, что каждый поток не использует одинаковые случайные числа.

1
ответ дан 18 December 2019 в 07:10
поделиться

rand () - это блокирующая функция. Значит, внутри есть критическая секция.

2
ответ дан 18 December 2019 в 07:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: