FortranからCUDAを呼ぶその2:CUDAをFortranから呼び出してみる
CUDAを呼び出してみます。題材とさせて貰うのは、GPGPU 勉強会 - CUDA Samplesの配列の足し算/最低限 GPGPUです。
vecadd_v1.cu→「vecadd_v1_CUDA.cu, vecadd_v1_main.f90」へと書き換えました。以下code例です。
vecadd_v1_CUDA.cu
#include <stdio.h> // 配列の足し算を行う関数 __global__ void vecadd(float *x, float *y, float *z, int N) { int i; for(i = 0; i < N; i++) z[i] = x[i] + y[i]; } void vecaddv1(float *x, float *y, float *z, int N) { // int N=10; // 配列のサイズを指定する int i, size; // float x[N], y[N], z[N]; float *xd, *yd, *zd; // 初期値の設定 // for(i = 0; i < N; i++) // { // x[i] = i + 1.0; // y[i] = i + 2.0; // } // デバイスメモリの確保 size = N * sizeof(float); cudaMalloc((void**)&xd, size); cudaMalloc((void**)&yd, size); cudaMalloc((void**)&zd, size); // ホスト側のデータをデバイス側にコピー cudaMemcpy(xd, x, size, cudaMemcpyHostToDevice); cudaMemcpy(yd, y, size, cudaMemcpyHostToDevice); // ここで足し算を行う vecadd<<<1, 1>>>(xd, yd, zd, N); // デバイス側のデータをホスト側にコピー cudaMemcpy(z, zd, size, cudaMemcpyDeviceToHost); // 出力 for(i = 0; i < N; i++) { printf("%d: %f\n", i, z[i]); } // デバイスメモリの開放 cudaFree(xd); cudaFree(yd); cudaFree(zd); } extern "C" void vecaddv1_(float *x, float *y, float *z, int *N) { vecaddv1(x, y, z, *N); }
vecadd_v1_main.f90
program vecadd_v1_main implicit none integer, parameter:: N=10 ! 配列のサイズを指定する integer:: i real(4):: x(N), y(N), z(N) ! 初期値の設定 do i=1,N x(i)=i-1 + 1.0 y(i)=i-1 + 2.0 enddo ! ここで足し算を行う call vecaddv1(x, y, z, N); ! 出力 do i=1,N write(*,*)i, z(i) enddo end program vecadd_v1_main
実行
% nvcc -c vecadd_v1_CUDA.cu % ifort vecadd_v1_CUDA.o vecadd_v1_main.f90 -o vecadd_v1.exe -lcudart -L/usr/local/cuda/lib64/ % ./vecadd_v1.exe
実行結果
0: 3.000000 1: 5.000000 2: 7.000000 3: 9.000000 4: 11.000000 5: 13.000000 6: 15.000000 7: 17.000000 8: 19.000000 9: 21.000000 1 3.000000 2 5.000000 3 7.000000 4 9.000000 5 11.00000 6 13.00000 7 15.00000 8 17.00000 9 19.00000 10 21.00000