Что такое C ++ версия циклического барьера Java?

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

CyclicBarrier barrier = new CyclicBarrier(2);

// thread 1
readA();
writeB();
barrier.await();
readB();
writeA();

// thread 2
readA();
writeB();
barrier.await();
readB();
writeA();

Есть ли точное или простое преобразование в C ++?

Также с OpenCL есть похожая инструкция:

readA();
writeB();
barrier(CLK_GLOBAL_MEM_FENCE);
readB();
writeA();

поэтому все соседние потоки ждут друг друга, но это только ограниченная реализация на языке Си.

2

Решение

C ++ STL не имеет циклического барьера. Вы можете предложить один комитет по стандартам 🙂

Такие компании, как Oracle или Microsoft, могут быстро решить, что добавить в библиотеку своего языка. Для C ++ люди должны прийти к соглашению, и это может занять некоторое время.

256 потоков это много. Как и во всех вопросах, связанных с производительностью, вам нужно измерить код, чтобы принять обоснованное решение. С 256 потоками я хотел бы использовать 10 барьеров, которые синхронизируются 11-м барьером. Вы должны измерить, чтобы знать, действительно ли это лучше.

Посмотрите мою C ++ реализацию циклического барьера, вдохновленную Java. Я написал это пару лет назад. Он основан на чьем-то (ошибочном) коде, который я нашел на http://studenti.ing.unipi.it/~s470694/a-cyclic-thread-barrier/ (ссылка больше не работает …) Код действительно прост (не нужно указывать мне). Конечно, это как есть, никаких гарантий.

// Modeled after the java cyclic barrier.
// Allows n threads to synchronize.
// Call Break() and join your threads before this object goes out of scope
#pragma once

#include <mutex>
#include <condition_variable>class CyclicBarrier
{
public:
explicit CyclicBarrier(unsigned numThreads)
: m_numThreads(numThreads)
, m_counts{ 0, 0 }
, m_index(0)
, m_disabled(false)
{ }

CyclicBarrier(const CyclicBarrier&) = delete;
CyclicBarrier(CyclicBarrier &&) = delete;
CyclicBarrier & operator=(const CyclicBarrier&) = delete;
CyclicBarrier & operator=(CyclicBarrier &&) = delete;

// sync point
void Await()
{
std::unique_lock<std::mutex> lock(m_requestsLock);
if (m_disabled)
return;

unsigned currentIndex = m_index;
++m_counts[currentIndex];

// "spurious wakeup" means this thread could wake up even if no one called m_condition.notify!
if (m_counts[currentIndex] < m_numThreads)
{
while (m_counts[currentIndex] < m_numThreads)
m_condition.wait(lock);
}
else
{
m_index ^= 1; // flip index
m_counts[m_index] = 0;
m_condition.notify_all();
}
}

// Call this to free current sleeping threads and prevent any further awaits.
// After calling this, the object is no longer usable.
void Break()
{
std::unique_lock<std::mutex> lock(m_requestsLock);
m_disabled = true;
m_counts[0] = m_numThreads;
m_counts[1] = m_numThreads;
m_condition.notify_all();
}

private:
std::mutex     m_requestsLock;
std::condition_variable m_condition;
const unsigned m_numThreads;
unsigned       m_counts[2];
unsigned       m_index;
bool           m_disabled;
};
1

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

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

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