1

我正在开发一个需要使用 Clang 将 OpenMP 卸载到 Nvidia GPU 的项目。按照此处提到的说明,我能够安装 Clang 以支持卸载。

系统规格

  • 操作系统 - Ubuntu 16.04 LTS
  • Clang-版本 4.00
  • 处理器 - Intel(R) Core(TM) i7 -4700MQ CPU
  • Cuda 版本 - 9.0
  • Nvidia GPU - GeForce 740M (sm_capability - 35)

但问题是当我执行一个示例程序来测试 OpenMP 到 Nvidia GPU 时,部分目标区域倾向于在 GPU 中运行,然后相同的目标区域开始在主机中执行。

请在此处找到示例程序,这是一个用于将 2 个矩阵相乘的小型 C 程序。

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

/* Problem size. */
# define N 1920

void init_array(float* A, float* B)
{
    int i, j;
    for (i = 0; i < N; i++)
    {
        for (j = 0; j < N; j++)
        {
            A[i*N + j] = ((float) i*j) / N;
        }
    }

    for (i = 0; i < N; i++)
    {
        for (j = 0; j < N; j++)
        {
            B[i*N + j] = ((float) i*(j+1)) / N;
        }
    }
}
void  mm_kernel(float *A, float *B, float *E)
{

    #pragma omp target data map(to:A) map(to:B) map(alloc:E)
{
    #pragma omp target
    #pragma omp teams distribute num_teams(4)
        for (int i = 0; i < N; i++)
  {
        printf("Team %d Thread %d Number of threads %d \n", omp_get_team_num() ,omp_get_thread_num(),omp_get_num_threads());
        #pragma omp  parallel for
        for (int j = 0; j < N; j++)
    {
            E[i*N + j] = 0.0;
            for(int k = 0; k < N; k++)
            {
                E[i*N + j] = E[i*N + j] + A[i*N + k] * B[j*N+k];
            }
    }
    }
  }
    }

int main(){
  double t_start, t_end;

    float* A;
    float* B;
    float* E;

    A = (float*)malloc(N*N*sizeof(float));
    B = (float*)malloc(N*N*sizeof(float));
    E = (float*)malloc(N*N*sizeof(float));
    init_array(A, B); //initialize Matrix A and B

    t_start = omp_get_wtime();
    mm_kernel(A,B,E);
    t_end = omp_get_wtime();

    printf("Time spent %lf\n",t_end-t_start );
    free(A);
    free(B);
    free(E);
}

该程序是使用

clang -fopenmp -fopenmp-targets=nvptx64-nvidia-cuda 3mm.c -o 3mmgpu 

声称目标区域正在主机和目标设备中执行的主要原因是由于命令行的输出。

命令行输出

首先,团队 0 和团队 1 显示每个团队 960 个,后来的迭代为每个团队提供 2 个线程(我的处理器是 4 核处理器,每个核心能够处理 2 个硬件级线程。)。

我还尝试使用 nvprof 执行 fat 二进制文件,以验证 GPU 中是否正在执行任何操作。

分析结果如下。

分析结果

实际上我无法理解目标区域发生了什么。为什么要在主机和目标设备中执行目标区域。

4

1 回答 1

2

我正在发布问题的答案,因为我终于能够弄清楚代码中出了什么问题。问题是目标设备崩溃中的卸载区域,因为我错误地将数据映射到 GPU。我只映射了指针而没有在 GPU 中分配内存。因此,当 GPU 执行崩溃时,执行发生在主机中。

感谢@Alexey Bataev 指出这一点。

于 2018-04-09T16:13:55.060 回答