Multithreading OPENMP taskyield指令不在混合(OPENMP+;mpi)程序中生成任务

Multithreading OPENMP taskyield指令不在混合(OPENMP+;mpi)程序中生成任务,multithreading,mpi,openmp,yield,Multithreading,Mpi,Openmp,Yield,有两项任务。 一个通过mpi进行通信,另一个做一些很酷的事情。 我使用mpi非阻塞调用,以便允许正在运行的线程在等待信息时执行其他任务。 但它不起作用 对代码的一些解释。如果你愿意,你可以直接跳到代码。 它创建了两个过程。 第一个进程将休眠10秒,然后通过阻塞调用发送一些数据。 第二个进程(这是感兴趣的进程)将使用一个共享整数(done)创建两个线程。一个任务将被实例化一次,而另一个任务的实例化次数与线程的实例化次数相同(在本例中为2)。 第一个任务将使用一个非阻塞调用接收数据,并且应该产生数据

有两项任务。 一个通过mpi进行通信,另一个做一些很酷的事情。 我使用mpi非阻塞调用,以便允许正在运行的线程在等待信息时执行其他任务。 但它不起作用

对代码的一些解释。如果你愿意,你可以直接跳到代码。 它创建了两个过程。 第一个进程将休眠10秒,然后通过阻塞调用发送一些数据。 第二个进程(这是感兴趣的进程)将使用一个共享整数(done)创建两个线程。一个任务将被实例化一次,而另一个任务的实例化次数与线程的实例化次数相同(在本例中为2)。 第一个任务将使用一个非阻塞调用接收数据,并且应该产生数据,以便运行的线程可以执行另一个任务(但这不会发生)。此任务仅由一个线程运行。 第二个任务只是打印一些很酷的东西。此任务由两个线程实例化

代码如下:

if (rank == 0)
  {
    buffer[1000] = 5;
    sleep(10);
    printf("Process %d sent data\n", rank);
    MPI_Send(buffer, SIZE, MPI_DOUBLE, 1, 5, MPI_COMM_WORLD);
  }
  else if (rank == 1)
  {
#pragma omp parallel num_threads(2) shared (done)
    {
#pragma omp single nowait
      {
#pragma omp task
        {
          int flag = 0;
          printf("Thread %d is receiving data\n", omp_get_thread_num());
          MPI_Irecv(buffer, SIZE, MPI_DOUBLE, 0, 5, MPI_COMM_WORLD, &request);

          MPI_Test(&request, &flag, &status);
          while (flag == 0)
          {
            #pragma omp taskyield
            MPI_Test(&request, &flag, &status);
            printf("Thread %d is wasting time\n", omp_get_thread_num());
            sleep(1);
          }

          done=1;
          printf("Thread %d received data\n", omp_get_thread_num());
        }
      }

#pragma omp task 
      {
        printf("Thread %d entered to the cool task\n", omp_get_thread_num());
        while (done == 0)
        {
          printf("Thread %d is doing some cool stuff\n", omp_get_thread_num());
          sleep(1); /* Or not */
        }
      }
    }
  }
以下是输出:

Thread 0 is receiving data
Thread 1 entered to the cool task
Thread 1 is doing some cool stuff
Thread 0 is wasting time
Thread 1 is doing some cool stuff
Thread 0 is wasting time
Thread 1 is doing some cool stuff
Thread 0 is wasting time
Thread 1 is doing some cool stuff
Thread 0 is wasting time
Thread 1 is doing some cool stuff
Thread 0 is wasting time
Thread 1 is doing some cool stuff
Thread 0 is wasting time
Thread 1 is doing some cool stuff
Thread 0 is wasting time
Thread 1 is doing some cool stuff
Thread 0 is wasting time
Thread 1 is doing some cool stuff
Thread 0 is wasting time
Thread 1 is doing some cool stuff
Thread 0 is wasting time
Process 0 sent data
Thread 1 is doing some cool stuff
Thread 0 is wasting time
Thread 1 is doing some cool stuff
Thread 0 is wasting time
Thread 1 is doing some cool stuff
Thread 0 received data
Thread 0 entered to the cool task
如您所见,线程0在完成通信任务之前不会进入cool任务

编译命令:

mpicc -fopenmp pruebas.c -o prueba
mpirun -np 2 --allow-run-as-root ./prueba (worry not, read below)
执行命令:

mpicc -fopenmp pruebas.c -o prueba
mpirun -np 2 --allow-run-as-root ./prueba (worry not, read below)
其他资料:

The program is being ran in a docker container with ubuntu.
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10)
mpicc --show output: gcc -I/usr/lib/openmpi/include/openmpi/opal/mca/event/libevent2021/libevent -I/usr/lib/openmpi/include/openmpi/opal/mca/event/libevent2021/libevent/include -I/usr/lib/openmpi/include -I/usr/lib/openmpi/include/openmpi -pthread -Wl,-rpath -Wl,/usr/lib/openmpi/lib -Wl,--enable-new-dtags -L/usr/lib/openmpi/lib -lmpi

OpenMP规范并不要求
taskyield
做任何事情

taskyield构造指定可以挂起当前任务,以便执行不同的任务

因此,它允许重新调度,但不需要重新调度。(关于这一点,任务调度算法的描述也很清楚)。因此,gcc完全有权不重新安排时间

不过,我知道LLVM(和Intel)OpenMP运行时确实会产生效果,我们可以看到这一点,因此有一种可能性,即仅将LLVM运行时与二进制文件一起使用就足够了。或者,试试叮当声或


(完全披露:我为英特尔工作:-)

OpenMP规范不要求
taskyield
做任何事情,它说

taskyield构造指定可以挂起当前任务,以便执行不同的任务

因此,它允许重新调度,但不需要重新调度。(关于这一点,任务调度算法的描述也很清楚)。因此,gcc完全有权不重新安排时间

不过,我知道LLVM(和Intel)OpenMP运行时确实会产生效果,我们可以看到这一点,因此有一种可能性,即仅将LLVM运行时与二进制文件一起使用就足够了。或者,试试叮当声或

(完全披露:我在英特尔工作:-)