Какой порядок памяти я должен использовать для потока хоста, ожидающего рабочих потоков?

У меня есть код, который отправляет задачи в asio io_service объект для удаленной обработки. Насколько я могу судить, код ведет себя правильно, но, к сожалению, я не очень разбираюсь в упорядочении памяти, и я не уверен, какие порядки памяти следует использовать при проверке атомарных флагов для обеспечения оптимальной производительности.

//boost::asio::io_service;
//^^ Declared outside this scope
std::vector<std::atomic_bool> flags(num_of_threads, false);
//std::vector<std::thread> threads(num_of_threads);
//^^ Declared outside this scope, all of them simply call the run() method on io_service

for(int i = 0; i < num_of_threads; i++) {
io_service.post([&, i]{
/*...*/
flags[i].store(true, /*[[[1]]]*/);
});
}

for(std::atomic_bool & atm_bool : flags) while(!atm_bool.load(/*[[[2]]]*/)) std::this_thread::yield();

В общем, я хочу знать, что я должен заменить [[[1]]] а также [[[2]]]?

Если это помогает, код функционально похож на следующее:

std::vector<std::thread> threads;
for(int i = 0; i < num_of_threads; i++) threads.emplace_back([]{/*...*/});
for(std::thread & thread : threads) thread.join();

За исключением того, что мой код поддерживает потоки во внешнем пуле потоков и отправляет им задачи.

2

Решение

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

Это может быть сделано с использованием семантики release-receive:

flags[i].store(true, std::memory_order_release);
// ...
while (!atm_bool.load(std::memory_order_acquire)) ...

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

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]