27

我想知道 openacc 和 openmp 之间的主要区别是什么。MPI、cuda 和 opencl 呢?我了解 openmp 和 mpi 之间的区别,尤其是关于共享和分布式内存的部分它们中的任何一个都允许混合 gpu-cpu 处理设置吗?

4

4 回答 4

39

OpenMP 和 OpenACC 支持基于指令的并行编程。

OpenMP 支持在共享内存计算平台上进行并行编程,例如多核 CPU。它非常易于使用,因为它足以告诉编译器一些指令(代码注释或 pragma)关于如何提取触发合成输入源代码的并行版本的并行性。

以下是带有编译指示的 OpenMP“Hello World”程序示例

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[]) 
{
  int nthreads, tid;

  /* Fork a team of threads giving them their own copies of variables */
  #pragma omp parallel private(nthreads, tid)

  {
     /* Obtain thread number */
     tid = omp_get_thread_num();
     printf("Hello World from thread = %d\n", tid);

     /* Only master thread does this */
     if (tid == 0) 
     {
        nthreads = omp_get_num_threads();
        printf("Number of threads = %d\n", nthreads);
     }

  }  /* All threads join master thread and disband */

}

上述代码的来源是OpenMP 练习,您可以从中找到许多其他示例。在这个“Hello World”示例中,主线程将输出涉及的线程数,而每个线程将从 thread = xxx 打印 Hello World

OpenACC 是编译器指令的集合,用于指定 C/C++ 或 Fortran 代码的一部分,以通过附加的加速器(作为 GPU)进行加速。它遵循与 OpenMP 几乎相同的理念,并且能够创建高级主机+加速器程序,同样无需管理加速器编程语言。例如,OpenACC 可以让您简单地加速现有的 C/C++ 代码,而无需学习 CUDA(当然会有一些性能损失)。

典型的 OpenACC 代码如下所示

#pragma acc kernels loop gang(32), vector(16)
for (int j=1; j<n-1; j++)
{
#pragma acc loop gang(16), vector(32)
    for (int i=1; i<m-1; i++)
    {
       Anew[j][i] = 0.25f * (A[j][i+1] + A[j-1][i]);
       ...
    }
}    

上面的源代码取自博客An OpenACC Example (Part 1),您可以在其中找到一些更有用的材料来了解 OpenMP 和 OpenACC 之间的区别。

其他来源如下

OpenACC API 与 OpenMP API 有什么关系?.

OpenACC 和 OpenMP 指令

Shane Cook,CUDA 编程,Morgan Kaufmann(第 10 章)

由于其本质,OpenACC 支持混合 CPU+GPU 编程。您还可以混合使用 OpenMP 和 OpenACC 指令。例如,在一个 4-GPU 系统中,您可以创建 4 个 CPU 线程来将计算工作卸载到 4 个可用的 GPU。这在 Shane Cook 的书中有所描述。但是,应该提到的是,OpenMP 4.0 还预见了将工作卸载到附加加速器的指令,请参阅

关于附加加速器指令的 OpenMP 技术报告 1

于 2013-10-21T14:11:01.660 回答
-1

OpenAcc 和 OpenMPI 支持基于指令的并行计算。OpenMPI 尝试利用多个 CPU 内核,OpenAcc 尝试利用 GPU 内核。

MPI——消息解析接口,是集群中节点间和节点内通信的编程模型规范。MPI程序的进程有一个私有的地址空间,它允许程序运行在一个分布式的内存空间(集群)上。通常 MPI 用于高性能计算,其中使用具有高带宽和低延迟的通信协议(如 Infiniband 等)。

随着 CUDA 和 OpenMP 等并行计算技术的最新发展,MPI 在其规范中添加了功能,以利用 cpu/gpu 内核提供的并行计算。

CUDA-Aware-MPI 和/或混合编程模型 (MPI + OpenMP) 已经在使用中。这意味着最终应用程序程序员可以编写相同的 MPI 程序,而无需显式处理 CUDA 或 OpenMP。这减轻了最终用户的负担。

对于没有 CUDA_aware-GPU 的示例, MPI_Send 和 d MPI_Recv 的代码就像

//MPI rank 0
cudaMemcpy(s_buf_h,s_buf_d,size,cudaMemcpyDeviceToHost);
MPI_Send(s_buf_h,size,MPI_CHAR,1,100,MPI_COMM_WORLD);

//MPI rank 1
MPI_Recv(r_buf_h,size,MPI_CHAR,0,100,MPI_COMM_WORLD, &status);
cudaMemcpy(r_buf_d,r_buf_h,size,cudaMemcpyHostToDevice);

但使用 CUDA_awre_MPI

//MPI rank 0
MPI_Send(s_buf_d,size,MPI_CHAR,1,100,MPI_COMM_WORLD);

//MPI rank n-1
MPI_Recv(r_buf_d,size,MPI_CHAR,0,100,MPI_COMM_WORLD, &status);

MPI 库将解决将主机内存缓冲区转换为 GPU 缓冲区的问题。

于 2016-02-10T01:56:24.557 回答
-1

阅读共享和分布式范例,您的问题可以在两个研究生级别的课程中得到更详细的回答,如果您真的对动手学习感兴趣,我建议您参加 TACC(德克萨斯高级计算中心)暑期培训

于 2018-05-18T21:16:12.450 回答
-2

首先,我从未使用 OpenMP/MPI/OpenAcc/Cuda 进行编程。我知道的唯一 API 是 OpenCL,所以要小心我在下面所说的,它需要确认:p!

我对 OpenCL 更满意,但我认为 Cuda 和 OpenCL 在编译过程中没有太大区别:编译器将内联函数(即 C 代码中的内核)。然后,在您的 OpenCL / Cuda 程序中,您可以在两个 GPU 任务之间进行 CPU 操作。

对于他们来说,有几种内存类型:

  • global : 由 cpu 和 gpu 读/写
  • local :仅由 gpu 读/写。
  • private : 一个简单内核的内存,其中存储了内核中声明的所有变量(仅限 gpu-core)
  • 常量:用于常量定义的内存(仅限 gpu-core)

关于它还有更多要说的,但你可以很容易地在网上找到关于它的好指南。

然后因为他们的编译是内联的,你可以做一个 GPU / CPU 程序。你甚至可以在同一个程序中使用 OpenMP 和 OpenCL,我看不出有什么问题。

于 2013-10-21T13:13:15.780 回答