Безопасно ли обновлять объект в потоке без блокировок, если другие потоки не получат к нему доступ? - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть вектор сущностей. В цикле обновления я перебираю вектор и обновляю каждую сущность: считываю ее позицию, вычисляю текущую скорость, пишу обновленную позицию. Кроме того, в процессе обновления я могу изменить некоторые другие объекты в другой части программы, но каждый этот объект, связанный только с текущей сущностью и другими сущностями, не будет касаться этого объекта.

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

Нужны ли здесь какие-либо блокировки? Я предполагаю, что все должно работать без мьютексов и т. Д. Я прав?

Ответы [ 2 ]

1 голос
/ 06 ноября 2019

Короткий ответ

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

Более длинный ответ

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

Обратите внимание, что, как указано @ acelent в разделе комментариев, если вам нужны изменения, сделанные одним потоком,видимый в другом потоке, вам может потребоваться какая-то синхронизация из-за того факта, что в зависимости от модели памяти и HW изменения, сделанные в одном потоке, могут быть не сразу видны в другом.

Это означает, что вы можете записать из Thread 1 в переменную и через некоторое время прочитать ту же память из Thread 2, но при этом не сможете увидеть запись, сделанную Thread 1.

0 голосов
/ 07 ноября 2019

«Я разделяю вектор на несколько фрагментов и обновляю каждый фрагмент в разных потоках» - в этом случае вам не требуется какой-либо механизм блокировки или синхронизации, однако производительность системы может значительно снизиться из-за ложного совместного использования в зависимости от того, как блокивыделены темы. Обратите внимание, что компилятор может исключить ложное совместное использование, используя частные временные переменные потока.

Вы можете найти много информации в книгах и вики. Вот некоторая информация https://software.intel.com/en-us/articles/avoiding-and-identifying-false-sharing-among-threads Также здесь есть сообщение о переполнении стека происходит ли ложное совместное использование при чтении данных в openmp?

...