0

長さ "N" 要素の 2 つのベクトルを乗算し、同じ長さの積ベクトルを CUDA 5.0 で返すコードを書きました。これが私のコードです。「N」の値を変更して、CPU と比較して GPU がどのように機能するかを確認してください。私は2000000000要素まで行くことができます。ただし、3000000000 に移動すると、次の警告が表示されます。

vecmul.cu(52): warning: floating-point value does not fit in required integral type

vecmul.cu(52): warning: floating-point value does not fit in required integral type

vecmul.cu: In function `_Z6vecmulPiS_S_':
vecmul.cu:15: warning: comparison is always false due to limited range of data type
vecmul.cu: In function `int main()':
vecmul.cu:40: warning: comparison is always true due to limited range of data type

そして、ここに私のコードがあります

 // Summing 2 Arrays

#include<stdio.h>
#include <fstream>

#define N (3000000000)

//const int threadsPerBlock = 256;

// Declare add function for Device

__global__ void vecmul(int *a,int *b,int *c)
{
    int tid = threadIdx.x + blockIdx.x * blockDim.x;
    if (tid >= N) {return;}  // (LINE 15) 

    c[tid] = a[tid] * b[tid];
}  


int main(void)
{
// Allocate Memory  on Host
int  *a_h = new int[N];
int  *b_h = new int[N];
int  *c_h = new int[N];

// Allocate Memory on GPU

int *a_d;
int *b_d;
int *c_d;  

cudaMalloc((void**)&a_d,N*sizeof(int));
cudaMalloc((void**)&b_d,N*sizeof(int));
cudaMalloc((void**)&c_d,N*sizeof(int));

//Initialize Host Array

for (int i=0;i<N;i++)   // (LINE 40)
{
    a_h[i] = i;
    b_h[i] = (i+1);
}  

// Copy Data from Host to Device

cudaMemcpy(a_d,a_h,N*sizeof(int),cudaMemcpyHostToDevice);
cudaMemcpy(b_d,b_h,N*sizeof(int),cudaMemcpyHostToDevice);

// Run Kernel
int blocks = int(N - 0.5)/256 + 1;   // (LINE 52)
vecmul<<<blocks,256>>>(a_d,b_d,c_d);

// Copy Data from Device to Host

cudaMemcpy(c_h,c_d,N*sizeof(int),cudaMemcpyDeviceToHost);

// Free Device Memory

cudaFree(a_d);
cudaFree(b_d);
cudaFree(c_d);


// Free Memory from Host

free(a_h);
free(b_h);
free(c_h);

return 0;
}

これは、この配列サイズに対してブロック数が十分でないためでしょうか? 私はCUDAの初心者なので、どんな提案も大歓迎です。これを NVIDIA Quadro 2000 で実行しています。

4

1 に答える 1

2

エラーは、32 ビットの符号付き int のオーバーフローが原因で発生します。2147483648 は最大 32 ビットの符号付き int であるため、N は常に負になり、警告で指定されているようにブール値テストは常に true/false を返します。

もう一つの問題は周りです

int blocks = int(N - 0.5)/256 + 1;   // (LINE 52)

N を浮動小数点に変換してから int に戻そうとしています。浮動小数点数の値が大きすぎます - これも 32 ビットの int をオーバーフローしたためです。

int() を削除できれば、256 で除算すると十分に小さくなるので機能すると思いますが、除算の前に強制的に int にするため、大きすぎてエラーが発生します。問題なのはブロックへの代入ではなく、明示的な int への変換です。

編集: N と浮動小数点と int の計算上の問題のいくつかを修正したので、オーバーフローの問題が発生しているのかどうか疑問に思っています。例えば:

for (int i=0;i<N;i++)   // (LINE 40)
{
    a_h[i] = i;
    b_h[i] = (i+1);
}  

N が 2^31-1 を超える場合、これは常に true になります (少なくとも i がオーバーフローするまで。これにより、これが無限ループになるか、2^31-1 の反復を実行してから終了する必要がありますか? コンパイラはそれを言いますALWAYS は true であり、その場合、ループは決して終了しません。

また、CUDAでsize_tが何かわかりませんが、

cudaMemcpy(c_h,c_d,N*sizeof(int),cudaMemcpyDeviceToHost);

N*sizeof(int) を実行すると、N=3B の場合は 2^31 を超え、さらには 2^32 を超えます。

ある時点で、なぜこれほど多くのスペースを割り当てようとしているのか、またより良い方法があるかどうかを自問する必要があります。

于 2013-06-11T01:47:51.817 に答える