我有以下cuda Kernel:
template <class T,typename Func>
__global__
void for_each_kernel (T* d_v,int N,Func f)
{
int idx = blockIdx.x*blockDim.x + threadIdx.x;
int num_threads = gridDim.x * blockDim.x;
__shared__ T s_x[1024];
for(int i = idx; i < N; i += num_threads)
{
s_x[threadIdx.x] = d_v[i];
f(&s_x[threadIdx.x]); // This Does Not Work Correctly
//s_x[threadIdx.x] *= 10; // This Works Correctly
d_v[i] = s_x[threadIdx.x];
}
}
当我拨打function f
时,它会输出错误的值。但是当我直接进行乘法运算时,它就可以了。
两个部分都在评论中突出显示。
这是传递的函数:
__device__
void func(int *x)
{
*x = (*x) * 10;
}
以下是内核调用的发生方式:
template <typename Func>
void for_each (int start,int end,Func f)
{
for_each_kernel<<<26,1024>>> (d_v,end-start+1,f);
}
a [i]中的每一个都被初始化为i。
我正在打印的值为a[10]
,应打印100。
但它是打印32767,这是2 ^ 15 - 1。
显示问题的完整示例代码如下:
#include <cstdio>
using namespace std;
__device__
void func(int *x)
{
*x = (*x) * 10;
}
template <class T,typename Func>
__global__
void for_each_kernel (T* d_v,int N,Func f)
{
int idx = blockIdx.x*blockDim.x + threadIdx.x;
int num_threads = gridDim.x * blockDim.x;
__shared__ T s_x[1024];
for(int i = idx; i < N; i += num_threads)
{
s_x[threadIdx.x] = d_v[i];
f(&s_x[threadIdx.x]);
//s_x[threadIdx.x] *= 10;
d_v[i] = s_x[threadIdx.x];
}
}
template <class T>
class device_vector
{
T *d_v;
int numEle;
public :
device_vector (T *h_v,int N)
{
cudaMalloc ((T**)&d_v,N*sizeof(T));
cudaMemcpy(d_v, h_v, N * sizeof(T), cudaMemcpyHostToDevice);
numEle = N;
}
void set (T data,int index)
{
cudaMemcpy (&d_v[index],&data,sizeof(T),cudaMemcpyHostToDevice);
}
T get (int index)
{
T temp;
cudaMemcpy (&temp,&d_v[index],sizeof(T),cudaMemcpyDeviceToHost);
return temp;
}
void getRange (T *dest,T *start,int N)
{
cudaMemcpy (dest,start,sizeof(T)*N,cudaMemcpyDeviceToHost);
}
// Only Provide Start And End Vertices Fot Which you Want To Do Some Operation
template <typename Func>
void for_each (int start,int end,Func f)
{
for_each_kernel<<<26,1024>>> (d_v,end-start+1,f);
}
};
int a[1<<28];
int main ()
{
int N = 1<<28;
for (int i=0;i<N;i++)
a[i] = i;
device_vector<int> d (a,N);
d.for_each (0,N-1,func);
printf ("Getting Element At Index %d : %d \n",100,d.get(10));
return 0;
}
答案 0 :(得分:3)
问题是您正在将__device__
函数指针从主机传递到内核。直接从主机获取设备符号的地址是非法的。您必须使用cudaMemcpyFromSymbol
来获取主机端设备符号的地址。
在当前代码中,您必须创建一个指向__device__
函数的主机端函数指针并将其传递给内核。它可以按如下方式完成:
//Declare function pointer
typedef void(*pFunc)(int*);
//Function pointer on device
__device__ pFunc f_device = func;
int main()
{
int N = 1 << 28;
for (int i = 0; i<N; i++)
a[i] = i;
device_vector<int> d(a, N);
//Function pointer on host
pFunc f_host;
//Copy address of device function to host
cudaMemcpyFromSymbol(&f_host, f_device, sizeof(pFunc));
d.for_each(0, N - 1, f_host);
printf("Getting Element At Index %d : %d \n", 100, d.get(100));
return 0;
}