C和OpenMP:do循环中的nowait for循环

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

我正在尝试最小化一些带有may参数的函数
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
的每个值的运行时分布以及magn
N的量级
这可能足以平衡负载

同样,它可能不是,您可能希望进一步研究
调度
子句,特别是
动态
引导
调度

如果没有任何上诉,请调查OpenMP
任务
构造;我现在没有时间(老实说,也没有技能)提供伪代码


最后,如果我误解了你的问题(这种情况经常发生),那么这个答案对你来说可能毫无价值。

从你的代码中提取一些东西,你似乎想写一些类似的东西

#pramga omp parallel for
    for(unsigned int i=0;i<N;i++){
        v[i] = foo(i)
    }
请注意
schedule
子句的引入,在本例中使用参数
dynamic
10
。这指示运行时将
i
的值束一次分发给各个线程,10个元素。这取决于
i
的每个值的运行时分布以及magn
N的量级
这可能足以平衡负载

同样,它可能不是,您可能希望进一步研究
调度
子句,特别是
动态
引导
调度

如果没有任何上诉,请调查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;iter
nowait
子句删除并行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!!!