Требуется ли блокировка мьютекса, когда каждый поток пишет в отдельную ячейку в общем массиве 2d

Нужен ли мьютекс в следующем параллельном вычислении клеточного автомата?

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

Мьютекс резко замедляет работу программы, но нужен ли он для того, чтобы данные в массиве 2d (futureOcean) оставались безопасными/непротиворечивыми?

Когда мьютекс блокирует futureOcean во время операций записи:

2 threads: 163.352990 seconds
5 threads: 515.739237 seconds
10threads: 1021.035517 seconds

Без использования мьютекса:

2 threads: 65.817534 seconds
10threads: 93.822217 seconds

Я реализую модель клеточного автомата, в частности, симуляцию рыбы, акулы и океана.

У меня есть двумерный массив 1000x600 с именем ocean, который, очевидно, представляет океан.

И еще один двумерный массив 1000x600 с именем futureOcean, в котором будут храниться состояния каждой ячейки для currentGeneration + 1.

Первоначально ocean заполняется:

  • 50% воды, т.е. 0 значений.
  • 25% рыбы т.е. положительные целые значения
  • 25% акула т.е. отрицательные целые значения

Обработка одного поколения включает правила обработки для каждой ячейки в пределах ocean.

Каждый раз, когда я вычисляю новое значение для текущей ячейки, я сохраняю его будущее значение во втором массиве 2d (futureOcean) в той же позиции row/column, что и исходное значение внутри ocean. Таким образом, каждая ячейка в futureOcean будет обновляться только один раз за поколение.

И я делаю это 20000 раз (поколений).


person bobbyrne01    schedule 09.12.2020    source источник


Ответы (1)


Если Ocean считывается исключительно во время создания нового поколения, потенциальные условия гонки отсутствуют и блокировка не требуется. Несколько потоков могут читать из постоянного источника без проблем.

Если каждое местоположение в futureOcean обновляется только один раз, то для этого местоположения нет конкурирующих записей, и блокировка не требуется. Отдельные потоки могут без проблем записывать в уникальные места, не затронутые другими потоками.

Затем вам придется дождаться полного обновления futureOcean перед запуском нового поколения, чтобы избежать чтения из него, пока он все еще записывается.

Вы можете повысить производительность многопоточной обработки, разделив работу таким образом, чтобы каждый поток выполнял запись в непрерывный раздел массива. В противном случае несколько потоков могли бы выполнять запись в расположения, расположенные близко друг к другу. Если это происходит на расстоянии одной или двух строк кэша (от 64 до 128 байтов в процессоре x86/64), то вы можете неоднократно аннулировать этот раздел памяти и принудительно перезагружать многоядерные кэши. (См. ложный обмен)

person rsjaffe    schedule 09.12.2020
comment
Это именно тот случай, ocean считывается исключительно во время создания нового поколения, каждое местоположение в futureOcean обновляется только один раз, и я жду, пока futureOcean полностью обновится, прежде чем начинать новое поколение - person bobbyrne01; 10.12.2020