Eve*_*one 2 c++ multithreading synchronization atomic
我有一堆线程正在处理多个数据项.线程必须按照我将数据传递给线程的相同顺序输出结果.那是:
Thread #1: give data - start processing
Thread #2: give data - start processing
Thread #3: give data - start processing
...
Thread #n: give data - start processing
Run Code Online (Sandbox Code Playgroud)
应该以与传递给线程的数据相同的顺序检索结果,而不管哪个线程首先完成处理.即:
Thread #1: put data
Thread #2: put data
...
Run Code Online (Sandbox Code Playgroud)
为了区分线程并管理它们,我给每个人一个ID (0,1,2,...,n).我正在使用ID为每个线程分配数据,以便它可以处理它.
for(int i=0; i<thread_count; i++)
give_data(i); // i is id and the function knows where to get data from
Run Code Online (Sandbox Code Playgroud)
我希望线程共享一个令牌,该令牌决定了预期产生结果的线程.所有线体都是相同的,主体看起来像:
while(true){
auto data = get_data();
result = process_data(data);
while(token != this_id) spin;
put_data(result); // this is a synchronized call
update_token(token);
}
Run Code Online (Sandbox Code Playgroud)
我的问题来自于token.我首先尝试了一个普通的引用(int & token),它显然无法工作(我没想到它).无论如何,我使用了一个静态变量,并且线程并不总是得到最新的.我很惊讶地看到一个主线支配一切.每当线程更新令牌时,它就会失去允许另一个线程放置其结果等等.但是,我有一个主线,好像令牌总是设置为自己的ID而不是更新.
如果我不得不猜测我会说这是一个缓存问题.但是,我不确定.
无论如何,我正在考虑使用std::atomic<int>我的令牌.会有用吗?如果没有,我还应该考虑做什么?什么是同步这些线程的更好方法?
额外:这感觉就像一个糟糕的设计,我不知道如何做得更好.任何建议将非常感谢.
无论如何,我使用了一个静态变量,并且线程并不总是得到最新的.我很惊讶地看到一个主线支配一切
是的,多个线程访问相同的非同步值,其中至少有一个写入它是数据争用,根据C++标准,这是未定义的行为.什么事情都可能发生.
我正在考虑使用std :: atomic作为我的令牌.会有用吗?
是.这可以防止令牌上的任何数据竞争.我没有在你的伪代码中看到任何其他直接问题,所以从这个角度来看它看起来不错.
这感觉就像一个糟糕的设计,我不知道如何做得更好.任何建议将非常感谢.
整个设计确实看起来有些奇怪,但如果有更简单的表达方式,它取决于您的线程库.例如,使用OpenMP,您可以在一次传递中执行此操作(背后的逻辑,give_data并且get_data太不清楚,以使其完整):
#pragma omp parallel
{
int threadCount = omp_get_num_threads();
#pragma omp single
for (int i = 0; i < threadCount; ++i)
give_data(i);
#pragma omp ordered for ordered schedule(static)
for (int i = 0; i < threadCount; ++i)
{
auto data = get_data();
result = process_data(data);
#pragma omp ordered
put_data(result); // this is a synchronized call
}
}
Run Code Online (Sandbox Code Playgroud)
该ordered指令强制put_data调用以完全相同的顺序(逐个)执行,就像循环是串行的一样,而线程仍然可以并行执行先前的数据处理.
如果您真正想要做的就是使一个大的数据处理循环与有序写入并行,那么使用OpenMP实际上可能会更容易:
#pragma omp parallel for ordered schedule(static)
for (int i = 0; i < dataItemCount; ++i)
{
auto data = get_data(i); // whatever this would entail
auto result = process_data(data);
#pragma omp ordered
put_data(result); // this is a synchronized call
}
Run Code Online (Sandbox Code Playgroud)
看起来您不需要按顺序排列数据项,但如果您确实这样做,那么这种方法就不会那么容易,因为每个有序循环只能有一个有序的部分.