我正在尝试使用may参数P
进行粒子群优化来最小化某些函数。你需要知道的是,这个过程需要为不同的索引foo
计算一个特定的函数(我称之为i
)(每个索引都链接到一组参数{{ 1}})。 P
在每个foo
上花费的时间是不可预测的,并且对于不同的i
可能会有很大差异。一旦计算了一个i
,我就想开始计算另一个v[i]
。当一个i
优化函数时,此过程将停止(这意味着已找到相应的参数集P
)。
所以我想用OpenMP并行化计算。我做了以下事情:
unsigned int N(5);
unsigned int last_called(0);
std::vector<double> v(N,0.0);
std::vector<bool> busy(N,false);
std::vector<unsigned int> already_ran(N,0);
std::vector<unsigned int> to_run_in_priority(N);
for(unsigned int i(0);i<N;i++){
to_run_in_priority[i]=i;
}
do{
#pramga omp parallel for nowait
for(unsigned int i=0;i<N;i++){
if(!busy[to_run_in_priority[i]]){
busy[to_run_in_priority[i]]=true;
already_ran[to_run_in_priority[i]]++;
foo(v[to_run_in_priority[i]]);
busy[to_run_in_priority[i]]=false;
}
/*update to_run_in_priority*/
}
} while (/*condition*/)
例如,如果我有4个线程,N = 5。该程序将进入for循环和午餐4个线程。当计算出第一个i
时,它将在第五个午餐时间。但接下来会发生什么?
代码是否会继续,达到while
条件并再次输入for
循环?如果确实如此,因为所有线程都忙,它会做什么?
如果我想做的事情不明确,请列出我想要的内容:
foo
)上为每个i
致电thread_numbers<N
foo
以查找某些i
(应运行的下一个i
必须与所有其他正在运行的i
不同,它应该是i
,其运行次数少于其他人。)如果我不够清楚,请毫不犹豫地询问精确度。
答案 0 :(得分:4)
从您的代码中抽象出来,您似乎想要编写类似
的内容#pramga omp parallel for
for(unsigned int i=0;i<N;i++){
v[i] = foo(i)
}
但你担心的是,因为调用foo(i)
的计算工作量变化很大,如果每个线程只获得一系列值i
的操作,这个简单的方法将很难平衡
您可能会感到担心,但我认为,如果我的诊断正确,那么您在平衡计划方面走错了路。你正在采取的错误方法是尝试自己编写工作分配。
试试这个(伪代码):
#pramga omp parallel for schedule(dynamic,10)
for(unsigned int i=0;i<N;i++){
v[i] = foo(i)
}
注意引入schedule
子句,在本例中引用参数dynamic
和10
。这会指示运行时将一串i
个值,每次10个元素分发给各个线程。根据{{1}}的每个值的运行时分布以及i
的大小,这可能足以平衡负载。
然后,它可能不会,您可能希望进一步调查N
子句,尤其是schedule
和dynamic
调度。
如果此上诉都没有调查OpenMP guided
构造;我没有时间(也不是说实话,技能)现在为此提供伪代码。
最后,如果我误解了你经常发生的问题,那么这个答案对你来说可能毫无价值。
答案 1 :(得分:0)
您可以尝试这样的事情:
#pragma omp parallel
{
#pramga omp for schedule(dynamic) nowait
for(unsigned int i=0;i<N;i++){
//parallel code with foo(i)
}
#pragma omp single
{
//serial code
}
}
假设N为5且有4个线程。四个线程开始运行,第一个完成的线程开始i = 4,第一个线程完成后进入单个语句。
答案 2 :(得分:0)
感谢您的意见和答案,这是我提出的解决方案。
unsigned int i(0);
unsigned int ip(0);
unsigned int N(10);
std::vector<bool> free(N,true)
#pragma omp parallel for schedule(dynamic,1) firstprivate(ip)
for(unsigned int iter=0; iter<maxiter_; iter++){
#pragma omp critical
{
i++;
ip = (i-1) % particle_.size();
if(!free_[ip]){iter -= 1;}
}
if(free_[ip]){
free_[ip]=false;
if(ip<2){sleep(2);}
else{ sleep(5);}
free_[ip]=true;
}
}
通过我做的几个测试,它似乎工作。但有没有人反对我的所作所为?