当内核中的内核调用(甚至递归调用)使用纹理内存来获取值时,我似乎遇到了麻烦。
如果子内核,比如说另一个内核,不使用纹理内存,一切都很好。如果我不在内核中调用内核,则结果是预期的。 只要我使用由于空间局部性和快速过滤而在我的情况下非常有用的纹理内存,cuda-memcheck 就会返回"Invalid __global__ write of size 4"。
我已经看到,在编程指南中的动态并行中,使用纹理内存时必须小心,这可能会导致数据不一致,但这里子内核甚至没有启动。
我试过 __syncthreads() 和 cudaDeviceSynchronize 在调用纹理内存之前或之后放置,但没有。
是否有一些已经报告的案例,是我做错了什么还是只是你不能那样使用纹理内存?
系统:gtx泰坦黑(sm_3.5),CUDA6.0。
编辑:一些示例代码来说明。
显然,之前已声明并填充了EField 。HANDLE_ERROR来自 book.h 包括来自CUDA 的示例
这是一个可编译的代码:
#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;
}