我要说的一件事是,您需要非常小心标准库的随机数函数。如果您的“ Simulator”类创建了一个生成器的实例,则不应使用同一对象并行运行Monte Carlo模拟,因为在运行之间您可能会得到重复的随机数模式,这将给您带来不准确的结果。
此领域的最佳做法是创建N个具有相同属性的Simulator对象,并为每个对象提供不同的随机种子。然后,您可以使用OpenMP(多个用于科学软件开发的常见并行编程模型)在多个线程上汇集这些对象。
std::vector<SimResult> generateResults(size_t N_runs,double seed)
{
std::vector<SimResult> results(N_runs);
#pragma omp parallel for
for(auto i = 0; i < N_runs; i++)
{
auto sim = Simulator(seed + i);
results[i] = sim.GetResult();
}
}
编辑:使用OpenMP,您可以选择不同的调度模型,例如在线程之间动态拆分工作。您可以执行以下操作:
#pragma omp parallel for schedule(dynamic,16)
这将使每个线程一次可以处理16个项目。
,
由于您已经知道要使用多少个元素并且从不更改向量的大小,所以最简单的解决方案是让每个线程都在向量的自己部分上工作。例如
更新
为适应不同的计算时间,您应保留当前代码,但应通过std::lock_guard
避免出现竞争情况。您将需要一个std::mutex
对于所有线程都是相同的,例如全局变量,或者将互斥量的引用传递给每个线程。
void fill(int RandSeed,std::mutex &nextItemMutex)
{
Simulator sim{RandSeed};
size_t workingIndex;
while(true)
{
{
// enter critical area
std::lock_guard<std::mutex> nextItemLock(nextItemMutex);
// Acquire next item
if(LastAdded < Max)
{
workingIndex = LastAdded;
LastAdded++;
}
else
{
break;
}
// lock is released when nextItemLock goes out of scope
}
// Do some work to bring foo to the desired state
// The duration of this work is subject to randomness
vec[workingIndex] = sim.GetResult();//Produces SimResult.
}
}
问题是,同步非常昂贵。但是,与您运行的仿真相比,它可能不算昂贵,所以也不错。
版本2:
要减少所需的同步量,您可以获取要处理的块,而不是单个项目:
void fill(int RandSeed,std::mutex &nextItemMutex,size_t blockSize)
{
Simulator sim{RandSeed};
size_t workingIndex;
while(true)
{
{
std::lock_guard<std::mutex> nextItemLock(nextItemMutex);
if(LastAdded < Max)
{
workingIndex = LastAdded;
LastAdded += blockSize;
}
else
{
break;
}
}
for(size_t i = workingIndex; i < workingIndex + blockSize && i < MAX; i++)
vec[i] = sim.GetResult();//Produces SimResult.
}
}
简单版本
void fill(int RandSeed,size_t partitionStart,size_t partitionEnd)
{
Simulator sim{RandSeed};
for(size_t i = partitionStart; i < partitionEnd; i++)
{
// Do some work to bring foo to the desired state
// The duration of this work is subject to randomness
vec[i] = sim.GetResult();//Produces SimResult.
}
}
main()
{
//launch a bunch of std::async that start
auto fut1 = std::async(fill,1,Max / 2);
auto fut2 = std::async(fill,2,Max / 2,Max);
// ...
}
本文链接:https://www.f2er.com/2658716.html