C和OpenMP:do循环中的nowait for循环
我正在尝试最小化一些带有may参数的函数C和OpenMP:do循环中的nowait for循环,c,multithreading,openmp,C,Multithreading,Openmp,我正在尝试最小化一些带有may参数的函数p进行粒子群优化。您需要知道的是,这个过程需要为不同的索引I(每个索引链接到一组参数P)计算特定的函数(我称之为foo)。foo在每个i上花费的时间是不可预测的,并且不同的i会有很大的差异。一旦计算出一个v[i],我想开始计算另一个。当一个i优化函数时,此过程停止(这意味着已找到相应的参数集P) 所以我想用OpenMP来并行计算。我会做以下事情: unsigned int N(5); unsigned int last_called(0); std::v
p
进行粒子群优化。您需要知道的是,这个过程需要为不同的索引I
(每个索引链接到一组参数P
)计算特定的函数(我称之为foo
)。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*/)
无符号整数N(5);
上次调用的无符号整数(0);
标准:向量v(N,0.0);
std::向量忙(N,false);
std::向量已运行(N,0);
std::在优先级中运行的向量(N);
对于(unsigned int i(0);i从您的代码中抽象出一些东西,您似乎希望编写如下内容
#pramga omp parallel for
for(unsigned int i=0;i<N;i++){
v[i] = foo(i)
}
请注意schedule
子句的引入,在本例中使用参数dynamic
和10
。这指示运行时将i
的值束一次分发给各个线程,10个元素。这取决于i
的每个值的运行时分布以及magnN的量级
这可能足以平衡负载
同样,它可能不是,您可能希望进一步研究调度
子句,特别是动态
和引导
调度
如果没有任何上诉,请调查OpenMP任务
构造;我现在没有时间(老实说,也没有技能)提供伪代码
最后,如果我误解了你的问题(这种情况经常发生),那么这个答案对你来说可能毫无价值。从你的代码中提取一些东西,你似乎想写一些类似的东西
#pramga omp parallel for
for(unsigned int i=0;i<N;i++){
v[i] = foo(i)
}
请注意schedule
子句的引入,在本例中使用参数dynamic
和10
。这指示运行时将i
的值束一次分发给各个线程,10个元素。这取决于i
的每个值的运行时分布以及magnN的量级
这可能足以平衡负载
同样,它可能不是,您可能希望进一步研究调度
子句,特别是动态
和引导
调度
如果没有任何上诉,请调查OpenMP任务
构造;我现在没有时间(老实说,也没有技能)提供伪代码
最后,如果我误解了你的问题(这种情况经常发生),那么这个答案对你来说可能是毫无价值的。你可以尝试以下方法:
#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
}
}
#pragma omp并行
{
#计划(动态)nowait的pramga omp
对于(unsigned int i=0;i您可以尝试以下方法:
#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
}
}
#pragma omp并行
{
#计划(动态)nowait的pramga omp
对于(unsigned int i=0;i感谢您的评论和回答,这就是我提出的解决方案
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;
}
}
无符号整数i(0);
无符号整数ip(0);
无符号整数N(10);
标准::无向量(N,真)
#pragma omp并行调度(动态,1)firstprivate(ip)
对于(unsigned int iter=0;iter,感谢您的评论和回答,这就是我提出的解决方案
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;
}
}
无符号整数i(0);
无符号整数ip(0);
无符号整数N(10);
标准::无向量(N,真)
#pragma omp并行调度(动态,1)firstprivate(ip)
for(unsigned int iter=0;iternowait
子句删除并行for循环中的隐式障碍。但是,您使用它的方式是没有用的,因为在并行块的末尾有一个无法删除的障碍。无论如何,High-Performance Mark建议使用schedule(动态)
似乎正是您想要的。nowait
子句删除了并行for循环中的隐式障碍。但是,您使用它的方式是无用的,因为在并行块的末尾有一个无法删除的障碍。无论如何,High-Perfroman Mark建议使用调度(动态)
似乎正是你想要的。谢谢你的回答!我已经知道了调度
命令,但这只有在foo
需要午餐的时间很长时才有用(即N>>线程数
)。如果是这样的话,那么平均而言,所有线程都应该同时停止。但是在我的例子中,N~线程的数量
,因此它不是很有用。但是你给了我一个想法……也许如果我改变foo所做的,如果当达到收敛标准时,for
循环停止,我可以找到一个解决方案。一半的问题em这里是设置为10的块大小。您不应该设置块大小,而应该使用默认值1。我发布了我的解决方案,如果您可以看一看并告诉我您的想法…tkx!!!谢谢您的回答!我已经知道schedule
命令,但这仅在需要设置时间foo
时才有用d很大(即N>>线程数。如果是这样的话,那么平均而言,所有线程都应该同时停止。但是在我的例子中,N~线程的数量
,因此它不是很有用。但是你给了我一个想法……也许如果我改变foo所做的,如果当达到收敛标准时,for
循环停止,我可以找到一个解决方案。一半的问题em这里是块大小被设置为10。你不应该设置块大小,而是使用默认值1。我发布了我的解决方案,如果你能看一下并告诉我你的想法…tkx!!!