CUDA动态并行:使用纹理内存时无效的全局写入

时间:2014-08-20 15:26:18

标签: c++ linux cuda dynamic-parallelism

当内核中的内核调用(甚至是递归调用)使用纹理内存来获取值时,我似乎遇到了麻烦。

如果子内核(比如说不同的内核)不使用纹理内存,一切都很好。如果我不在内核中调用内核,则结果是预期的结果。 只要我使用纹理内存,在我的情况下由于空间局部性和快速过滤非常有用,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;
}

1 个答案:

答案 0 :(得分:0)

将来,请提供完整的,可编辑的代码。所以期待this。作为不确定性的一个例子,您的内核定义是test_cdp。从主机代码调用的内核为test2_cdp。请不要让别人猜测你的意图,或者打20个问题来澄清你的代码。发布一个完整的,可编译的代码,不需要添加或更改,以证明问题。这就是你对问题进行投票的原因。

我可以看到2个问题。

  1. 如果您要修复上述问题,那么编写的代码可能会导致启动无休止的子内核链。您可能认为oneChild变量以某种方式在父内核和子内核之间共享。它不是。因此,每个启动的子内核都会看到oneChild为零,并且它将启动自己的子内核。我不知道这个序列会在哪里结束,但它不能合理地使用CDP。

  2. 从设备启动的内核引用的CDP does not support模块范围纹理。请改用texture objects