C和OpenMP:现在在do循环中循环

时间:2013-12-30 15:48:49

标签: c multithreading openmp

我正在尝试使用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,其运行次数少于其他人。)
  • 对前两个项目进行循环,直到达到收敛标准。

如果我不够清楚,请毫不犹豫地询问精确度。

3 个答案:

答案 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子句,在本例中引用参数dynamic10。这会指示运行时将一串i个值,每次10个元素分发给各个线程。根据{{​​1}}的每个值的运行时分布以及i的大小,这可能足以平衡负载。

然后,它可能不会,您可能希望进一步调查N子句,尤其是scheduledynamic调度。

如果此上诉都没有调查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;
    }
}
通过我做的几个测试,它似乎工作。但有没有人反对我的所作所为?