Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asynchronous CUDA流、纹理绑定和异步memcpy_Asynchronous_Concurrency_Cuda_Textures - Fatal编程技术网

Asynchronous CUDA流、纹理绑定和异步memcpy

Asynchronous CUDA流、纹理绑定和异步memcpy,asynchronous,concurrency,cuda,textures,Asynchronous,Concurrency,Cuda,Textures,在CUDA I中编写一些信号处理程序,最近在优化方面取得了巨大进展。通过使用1D纹理和调整我的访问模式,我成功地获得了10倍的性能提升。(我以前尝试过从全局内存到共享内存的事务对齐预取,但后来发生的不一致访问模式弄乱了扭曲→共享缓存银行关联(我想是) 现在我面临的问题是,CUDA纹理和绑定如何与异步memcpy交互 考虑以下内核 texture<...> mytexture; __global__ void mykernel(float *pOut) { pOut[thre

在CUDA I中编写一些信号处理程序,最近在优化方面取得了巨大进展。通过使用1D纹理和调整我的访问模式,我成功地获得了10倍的性能提升。(我以前尝试过从全局内存到共享内存的事务对齐预取,但后来发生的不一致访问模式弄乱了扭曲→共享缓存银行关联(我想是)

现在我面临的问题是,CUDA纹理和绑定如何与异步memcpy交互

考虑以下内核

texture<...> mytexture;

__global__ void mykernel(float *pOut)
{
    pOut[threadIdx.x] = tex1Dfetch(texture, threadIdx.x);
}

分层纹理不是一个选项,因为我拥有的数据量仅适用于未绑定到CUDA数组的普通1D纹理(请参见CUDA 4.2 C编程指南中的表F-2)。

事实上,您无法在不同流中使用纹理时解除绑定

由于流的数量不需要很大,以隐藏异步MeMCPYS(2已经做过),所以可以使用C++模板给每个流自己的纹理:

texture<float, 1, cudaReadModeElementType> mytexture1;
texture<float, 1, cudaReadModeElementType> mytexture2;

template<int TexSel> __device__ float myTex1Dfetch(int x);

template<> __device__ float myTex1Dfetch<1>(int x) { return tex1Dfetch(mytexture1, x); }
template<> __device__ float myTex1Dfetch<2>(int x) { return tex1Dfetch(mytexture2, x); }


template<int TexSel> __global__ void mykernel(float *pOut)
{
    pOut[threadIdx.x] = myTex1Dfetch<TexSel>(threadIdx.x);
}


int main(void)
{
    float *out_d[2];

    // ...

    mykernel<1><<<blocks, threads, stream[0]>>>(out_d[0]);
    mykernel<2><<<blocks, threads, stream[1]>>>(out_d[1]);

    // ...
}
纹理mytexture1;
纹理2;
模板uuu设备uuu浮点myTex1Dfetch(int x);
模板uuu设备uuu浮点myTex1Dfetch(int x){返回tex1Dfetch(mytexture1,x);}
模板uuu设备uuu浮点myTex1Dfetch(int x){返回tex1Dfetch(mytexture2,x);}
模板\uuuu全局\uuuuu无效mykernel(float*pOut)
{
pOut[threadIdx.x]=myTex1Dfetch(threadIdx.x);
}
内部主(空)
{
浮动*out_d[2];
// ...
mykernel(out_d[0]);
mykernel(out_d[1]);
// ...
}

我不确定,但我认为这样重新绑定纹理会导致问题。然而,OpenCL允许创建纹理数组,所以如果你不能解决CUDA的问题,你可以考虑切换到OpenCL,它通常是非常简单的。@ Aland:你知道类似的Cufft的OpenCL对应吗?我不知道更多或更少的已建立的库,但是在因特网上有很多代码,因此,您可能会找到适合您需要的内容。如何使用模板纹理引用?我想到的是(完全未经测试!)您的评论似乎缺少一些内容。@datenwolf,不要使用模板纹理引用。声明多个纹理引用,然后根据模板参数将内核模板化为从一个纹理引用读取。然后将内核包装在模板宿主代码中,该代码绑定与模板参数对应的纹理引用,然后使用模板参数调用内核。(将多个纹理引用绑定到同一CUDA数组是无害的。)轮到我了。我个人优化了现实生活中的HPC代码,其中两个流足以将主机/设备通信几乎完美地隐藏在内核执行之后。当内核在一个流中执行时,异步拷贝在另一个流中执行。使用cudaStreamWaitEvent进行了一点跨流同步,以确保在数据被另一个线程使用之前,拷贝实际上已经完成。显然,在某些情况下,可能需要两个以上的流才能获得最佳性能。
texture<...> texarray[N_CUDA_STREAMS];
texture<float, 1, cudaReadModeElementType> mytexture1;
texture<float, 1, cudaReadModeElementType> mytexture2;

template<int TexSel> __device__ float myTex1Dfetch(int x);

template<> __device__ float myTex1Dfetch<1>(int x) { return tex1Dfetch(mytexture1, x); }
template<> __device__ float myTex1Dfetch<2>(int x) { return tex1Dfetch(mytexture2, x); }


template<int TexSel> __global__ void mykernel(float *pOut)
{
    pOut[threadIdx.x] = myTex1Dfetch<TexSel>(threadIdx.x);
}


int main(void)
{
    float *out_d[2];

    // ...

    mykernel<1><<<blocks, threads, stream[0]>>>(out_d[0]);
    mykernel<2><<<blocks, threads, stream[1]>>>(out_d[1]);

    // ...
}