CUDA PTX f32.f32 纹理读取
CUDA PTX f32.f32 texture read
是否可以直接使用浮点索引从 CUDA 纹理中读取,例如我可以使用 tex.1d.v4.f32.f32
.
执行纹理获取吗
在查看 .ptx
文件时,这似乎节省了两条指令,这反映在基准测试时性能的提高。然而,相当关键的缺点是,虽然这看起来 运行 没有问题,但它不会产生预期的结果。
下面的代码演示了这个问题:
#include "cuda.h"
#include <thrust/device_vector.h>
//create a global 1D texture of type float
texture<float, cudaTextureType1D, cudaReadModeElementType> tex;
//below is a hand rolled ptx texture lookup using tex.1d.v4.f32.f32
__device__
float tex_load(float idx)
{
float4 temp;
asm("tex.1d.v4.f32.f32 {%0, %1, %2, %3}, [tex, {%4}];" :
"=f"(temp.x), "=f"(temp.y), "=f"(temp.z), "=f"(temp.w) : "f"(idx));
return temp.x;
}
//Try to read from the texture using tex1Dfetch and the custom tex_load
__global__ void read(){
float x = tex1Dfetch(tex,0.0f);
float y = tex_load(0.0f);
printf("tex1Dfetch: %f tex_load: %f\n",x,y);
}
int main()
{
//create a vector of size 1 with the x[0]=3.14
thrust::device_vector<float> x(1,3.14);
float* x_ptr = thrust::raw_pointer_cast(&x[0]);
//bind the texture
cudaBindTexture(0, tex, x_ptr, sizeof(float));
//launch a single thread single block kernel
read<<<1,1>>>();
cudaUnbindTexture(tex);
return 0;
}
我已经在几张卡(K40、C2070)和几个 CUDA 版本(6.0、7.0)上进行了尝试,但总的来说我得到了相同的输出:
tex1Dfetch: 3.140000 tex_load: 0.000000
这可能吗,还是我找错树了?
您的问题是您对纹理使用了不受支持的指令,该纹理使用默认 cudaReadModeElementType
读取模式绑定到线性内存。如果你像这样重写你的函数:
__device__
float tex_load(int idx)
{
float4 temp;
asm("tex.1d.v4.f32.s32 {%0, %1, %2, %3}, [tex, {%4}];" :
"=f"(temp.x), "=f"(temp.y), "=f"(temp.z), "=f"(temp.w) : "r"(idx));
return temp.x;
}
即。将整数索引传递给纹理单元,而不是浮点数,我想你会发现它会正常工作。您需要具有过滤读取模式的纹理才能使用 tex.1d.v4.f32.f32
.
是否可以直接使用浮点索引从 CUDA 纹理中读取,例如我可以使用 tex.1d.v4.f32.f32
.
在查看 .ptx
文件时,这似乎节省了两条指令,这反映在基准测试时性能的提高。然而,相当关键的缺点是,虽然这看起来 运行 没有问题,但它不会产生预期的结果。
下面的代码演示了这个问题:
#include "cuda.h"
#include <thrust/device_vector.h>
//create a global 1D texture of type float
texture<float, cudaTextureType1D, cudaReadModeElementType> tex;
//below is a hand rolled ptx texture lookup using tex.1d.v4.f32.f32
__device__
float tex_load(float idx)
{
float4 temp;
asm("tex.1d.v4.f32.f32 {%0, %1, %2, %3}, [tex, {%4}];" :
"=f"(temp.x), "=f"(temp.y), "=f"(temp.z), "=f"(temp.w) : "f"(idx));
return temp.x;
}
//Try to read from the texture using tex1Dfetch and the custom tex_load
__global__ void read(){
float x = tex1Dfetch(tex,0.0f);
float y = tex_load(0.0f);
printf("tex1Dfetch: %f tex_load: %f\n",x,y);
}
int main()
{
//create a vector of size 1 with the x[0]=3.14
thrust::device_vector<float> x(1,3.14);
float* x_ptr = thrust::raw_pointer_cast(&x[0]);
//bind the texture
cudaBindTexture(0, tex, x_ptr, sizeof(float));
//launch a single thread single block kernel
read<<<1,1>>>();
cudaUnbindTexture(tex);
return 0;
}
我已经在几张卡(K40、C2070)和几个 CUDA 版本(6.0、7.0)上进行了尝试,但总的来说我得到了相同的输出:
tex1Dfetch: 3.140000 tex_load: 0.000000
这可能吗,还是我找错树了?
您的问题是您对纹理使用了不受支持的指令,该纹理使用默认 cudaReadModeElementType
读取模式绑定到线性内存。如果你像这样重写你的函数:
__device__
float tex_load(int idx)
{
float4 temp;
asm("tex.1d.v4.f32.s32 {%0, %1, %2, %3}, [tex, {%4}];" :
"=f"(temp.x), "=f"(temp.y), "=f"(temp.z), "=f"(temp.w) : "r"(idx));
return temp.x;
}
即。将整数索引传递给纹理单元,而不是浮点数,我想你会发现它会正常工作。您需要具有过滤读取模式的纹理才能使用 tex.1d.v4.f32.f32
.