Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在同一线程上运行的所有OpenMP任务_C++_Multithreading_Task_Openmp - Fatal编程技术网

C++ 在同一线程上运行的所有OpenMP任务

C++ 在同一线程上运行的所有OpenMP任务,c++,multithreading,task,openmp,C++,Multithreading,Task,Openmp,我用OpenMP中的任务编写了一个递归并行函数。虽然它给了我正确的答案并且运行良好,但我认为并行性存在一个问题。与串行解决方案相比,运行时在我没有任务的情况下解决的其他并行问题中无法扩展。打印任务的每个线程时,它们都在线程0上运行。我正在Visual Studio Express 2013上编译和运行 int parallelOMP(int n) { int a, b, sum = 0; int alpha = 0, beta = 0; for (int k = 1;

我用OpenMP中的任务编写了一个递归并行函数。虽然它给了我正确的答案并且运行良好,但我认为并行性存在一个问题。与串行解决方案相比,运行时在我没有任务的情况下解决的其他并行问题中无法扩展。打印任务的每个线程时,它们都在线程0上运行。我正在Visual Studio Express 2013上编译和运行

int parallelOMP(int n)
{

    int a, b, sum = 0;
    int alpha = 0, beta = 0;

    for (int k = 1; k < n; k++)
    {

        a = n - (k*(3 * k - 1) / 2);
        b = n - (k*(3 * k + 1) / 2);


        if (a < 0 && b < 0)
            break;


        if (a < 0)
            alpha = 0;

        else if (p[a] != -1)
            alpha = p[a];

        if (b < 0)
            beta = 0;

        else if (p[b] != -1)
            beta = p[b];


        if (a > 0 && b > 0 && p[a] == -1 && p[b] == -1)
        {
            #pragma omp parallel
            {
                #pragma omp single
                {
                    #pragma omp task shared(p), untied
                    {
                        cout << omp_get_thread_num();
                        p[a] = parallelOMP(a);
                    }
                    #pragma omp task shared(p), untied
                    {
                        cout << omp_get_thread_num();
                        p[b] = parallelOMP(b);
                    }
                    #pragma omp taskwait
                }
            }

            alpha = p[a];
            beta = p[b];
        }

        else if (a > 0 && p[a] == -1)
        {
            #pragma omp parallel
            {
                #pragma omp single
                {
                    #pragma omp task shared(p), untied
                    {
                        cout << omp_get_thread_num();
                        p[a] = parallelOMP(a);
                    }

                    #pragma omp taskwait
                }
            }

            alpha = p[a];
        }

        else if (b > 0 && p[b] == -1)
        {
            #pragma omp parallel
            {
                #pragma omp single
                {
                    #pragma omp task shared(p), untied
                    {
                        cout << omp_get_thread_num();
                        p[b] = parallelOMP(b);
                    }

                    #pragma omp taskwait
                }
            }

            beta = p[b];
        }


        if (k % 2 == 0)
            sum += -1 * (alpha + beta);
        else
            sum += alpha + beta;


    }

    if (sum > 0)
        return sum%m;
    else
        return (m + (sum % m)) % m;
}
intparallecomp(intn)
{
int a,b,和=0;
int alpha=0,beta=0;
对于(int k=1;k0&&b>0&&p[a]=-1&&p[b]=-1)
{
#pragma-omp并行
{
#布拉格omp单曲
{
#pragma omp任务共享(p),未绑定
{

cout实际问题:

您正在使用Visual Studio 2013

Visual Studio从未支持2.0以上的OMP版本(请参阅)

OMP任务是OMP 3.0的一项功能(请参阅)

因此,使用VS意味着你没有OMP任务

如果OMP任务是一个基本的要求,使用不同的编译器。如果OMP不是一个基本的要求,你应该考虑一个可替代的并行任务处理库。VisualStudio包括MS并发运行时,以及它的内置。我最近从OMP转移到PPL,因为我用VS工作,它不是退出。e替代品数量减少,但功能相当强大


我第二次尝试解决这个问题,也是出于历史原因而保留下来的:

因此,问题几乎可以肯定,您正在
omp并行
区域之外定义
omp任务

下面是一个人为的例子:

void work()
{
    #pragma omp parallel
    {
        #pragma omp single nowait
        for (int i = 0; i < 5; i++)
        {
            #pragma omp task untied
            {
                std::cout << 
                    "starting task " << i << 
                    " on thread " << omp_get_thread_num() << "\n";

                sleep(1);
            }
        }
    }
}
但是如果你把它留在里面:

starting task starting task 3 on thread 1
starting task 0 on thread 3
2 on thread 0
starting task 1 on thread 2
starting task 4 on thread 2
成功,完成共享输出资源的真实滥用

(作为参考,如果省略
单个
声明,每个线程将运行循环,导致在我的4 cpu虚拟机上运行20个任务)


为完整起见,以下包含原始答案,但不再相关!

在任何情况下,您的
omp任务都是一件简单的事情。它可能会立即运行并完成:

#pragma omp task shared(p), untied
cout << omp_get_thread_num();

#pragma omp task shared(p), untied
cout << omp_get_thread_num();

#pragma omp task shared(p), untied
cout << omp_get_thread_num();

#pragma omp task shared(p), untied
cout << omp_get_thread_num();
#pragma omp任务共享(p),未绑定
cout有时我希望对SO的评论可以像答案一样格式丰富,但遗憾的是事实并非如此。因此,这里有一个伪装成答案的长评论

看来,编写递归OpenMP代码的一个非常常见的错误是不理解并行区域是如何工作的。考虑下面的代码(使用显式任务,因此支持OpenMP 3或更新所需的):

一旦启用嵌套并行,就会面临一个新问题。每次遇到嵌套并行区域时,遇到的线程都会生成一个额外的线程(因为
num_threads(2)
)或者从运行时的线程池中获取一个空闲线程。在每一个更深层次的递归中,此程序将需要两倍于上一层次的线程。尽管可以通过
OMP\u thread\u limit
设置线程总数的上限(另一个OpenMP 3.0功能)撇开开销不谈,在这种情况下,这并不是人们真正想要的

在这种情况下,正确的解决方案是在单个并行区域的动态范围内使用孤立任务:

void par_rec_func (int arg)
{
   if (arg <= 0) return;

   #pragma omp task
   par_rec_func(arg-1);

   #pragma omp task
   par_rec_func(arg-1);

   // Wait for the child tasks to complete if necessary
   #pragma omp taskwait
}

// somewhere in the main function
#pragma omp parallel
{
   #pragma omp single
   par_rec_func(10);
}

omp\u get\u level()
用于确定嵌套级别,而
if
子句用于在嵌套的第四级或更深层有选择地停用并行区域。此解决方案是愚蠢的,在递归树不平衡时无法正常工作。

是的,这就是我想要做的,但它仍然会产生相同的问题。@BenMcAlindin请修复此问题那么,他在你的问题中编写了代码。这很有意义(虽然我的课堂讲稿中没有),但仍然不起作用。我尝试将并行语句和单个语句放在几个地方:在每个任务之前,在parallecomp()的开头,在main()中调用parallecomp()之前我更新了代码,以显示在每个task@BenMcAlindin我自己组装了一个最小的示例,通过在
omp parallel
区域内调用
parallelOMP
,我得到了(如预期的那样)显示在不同线程上运行的任务的结果。也许您应该使用一个非常基本的OMP示例检查您是否启用了OMP,并且它正在运行,并且它可以访问多个内核。您能告诉我们哪个编译器(和版本)吗您正在使用以及如何构建可执行文件?宝贵的经验教训:永远不要假设其他人知道MS的最小OMP支持,并且始终询问OP他们首先使用的编译器;-)
if (a > 0 && b > 0 && p[a] == -1 && p[b] == -1)
{
    #pragma omp task shared(p), untied
    {
        cout << omp_get_thread_num();
        p[a] = parallelOMP(a);
    }

    #pragma omp task shared(p), untied
    {
        cout << omp_get_thread_num();
        p[b] = parallelOMP(b);
    }

    #pragma omp taskwait

    alpha = p[a];
    beta = p[b];
}
void par_rec_func (int arg)
{
   if (arg <= 0) return;

   #pragma omp parallel num_threads(2)
   {
      #pragma omp task
      par_rec_func(arg-1);

      #pragma omp task
      par_rec_func(arg-1);
   }
}

// somewhere in the main function
par_rec_func(10);
omp_set_nested(1);
void par_rec_func (int arg)
{
   if (arg <= 0) return;

   #pragma omp task
   par_rec_func(arg-1);

   #pragma omp task
   par_rec_func(arg-1);

   // Wait for the child tasks to complete if necessary
   #pragma omp taskwait
}

// somewhere in the main function
#pragma omp parallel
{
   #pragma omp single
   par_rec_func(10);
}
void par_rec_func (int arg)
{
   if (arg <= 0) return;

   int level = omp_get_level();

   #pragma omp parallel sections num_threads(2) if(level < 4)
   {
      #pragma omp section
      par_rec_func(arg-1);

      #pragma omp section
      par_rec_func(arg-1);
   }
}

// somewhere in the main function
int saved_nested = omp_get_nested();
omp_set_nested(1);

par_rec_func(10);

omp_set_nested(saved_nested);