当内核中的内核调用(甚至是递归调用)使用纹理内存来获取值时,我似乎遇到了麻烦。
如果子内核(比如说不同的内核)不使用纹理内存,一切都很好。如果我不在内核中调用内核,则结果是预期的结果。 只要我使用纹理内存,在我的情况下由于空间局部性和快速过滤非常有用,cuda-memcheck返回 “无效的__global__写入大小为4”
我已经看到,在编程指南中的动态并行性中,在使用可能导致数据不一致的纹理内存时必须小心,但这里的子内核甚至都没有启动。
我已经尝试在调用纹理内存之前或之后放置了__syncthreads()和cudaDeviceSynchronize,但没有。
是否有一些已经报道的案例,我做错了什么,或者只是你不能那样使用纹理记忆?
system:gtx titan black(sm_3.5),CUDA6.0。
编辑:一些示例代码来说明。
显然,之前已声明并填充 EField 。 HANDLE_ERROR 来自book.h来自CUDA by examples
这是一个可编辑的代码:
#include "cuda.h"
#include "/common/book.h"
#define DIM 2048
texture<float4, 2, cudaReadModeElementType> texEField;
__device__ int oneChild = 0;
__global__ void test_cdp( float x0, float y0 ){
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;
int idx = x + y * blockDim.x * gridDim.x;
printf("Propa started from thread %d\n", idx);
float4 E = tex2D( texEField, x0, y0 );
printf("E field %f -- %f\n", E.z, E.w);
if( oneChild < 1 ){
test_cdp<<<1, 1>>>(x0, y0);
oneChild++;
}
}
int main( void ){
//Start of texture allocation
float4 *EField = new float4 [DIM*DIM];
for( int u = 0; u < DIM*DIM; u++ ){
EField[u].x = 1.0f;
EField[u].y = 1.0f;
EField[u].z = 1.0f;
EField[u].w = 1.0f;
}
cudaChannelFormatDesc desc = cudaCreateChannelDesc<float4>();
float4 *dev_EField;
HANDLE_ERROR( cudaMalloc( (void**)&dev_EField, DIM * DIM * sizeof(float4) ) );
HANDLE_ERROR( cudaMemcpy( dev_EField, EField, DIM * DIM * sizeof(float4), cudaMemcpyHostToDevice ) );
HANDLE_ERROR( cudaBindTexture2D( NULL, texEField, dev_EField, desc, DIM, DIM, sizeof(float4) * DIM ) );
texEField.addressMode[0] = cudaAddressModeWrap;
texEField.addressMode[1] = cudaAddressModeWrap;
texEField.filterMode = cudaFilterModeLinear;
texEField.normalized = true;
test_cdp<<<1, 1>>>(0.5, 0.5);
HANDLE_ERROR( cudaFree( dev_EField ) );
HANDLE_ERROR( cudaUnbindTexture( texEField ) );
return 0;
}
答案 0 :(得分:0)
将来,请提供完整的,可编辑的代码。所以期待this。作为不确定性的一个例子,您的内核定义是test_cdp
。从主机代码调用的内核为test2_cdp
。请不要让别人猜测你的意图,或者打20个问题来澄清你的代码。发布一个完整的,可编译的代码,不需要添加或更改,以证明问题。这就是你对问题进行投票的原因。
我可以看到2个问题。
如果您要修复上述问题,那么编写的代码可能会导致启动无休止的子内核链。您可能认为oneChild
变量以某种方式在父内核和子内核之间共享。它不是。因此,每个启动的子内核都会看到oneChild
为零,并且它将启动自己的子内核。我不知道这个序列会在哪里结束,但它不能合理地使用CDP。
从设备启动的内核引用的CDP does not support模块范围纹理。请改用texture objects。