我有简单的内核:
__kernel vecadd(__global const float *A,
__global const float *B,
__global float *C)
{
int idx = get_global_id(0);
C[idx] = A[idx] + B[idx];
}
为什么当我将float更改为 float4 时,内核运行速度会慢30%以上?
所有教程都说,使用矢量类型可以加速计算......
在主机端,为float4参数分配的内存为16字节对齐,而clEnqueueNDRangeKernel的global_work_size为4倍。
内核运行在AMD HD5770 GPU上,AMD-APP-SDK-v2.6。
CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT的设备信息返回4.
修改
global_work_size = 1024 * 1024(及更高)
local_work_size = 256
使用CL_PROFILING_COMMAND_START和CL_PROFILING_COMMAND_END测量时间。
对于较小的global_work_size(浮动8196 /浮动448),矢量化版本更快,但我想知道,为什么?
答案 0 :(得分:5)
我不知道你提到的教程是什么,但它们必须陈旧。 ATI和NVIDIA现在都使用标量gpu架构至少五年。 现在在代码中使用向量只是为了方便语法,它没有普通标量代码的性能优势。 事实证明,标量架构对于GPU而言比向量更好 - 它更好地利用了硬件资源。
答案 1 :(得分:1)
我不确定为什么向量会慢得多,而不了解更多有关工作组和全局大小的信息。我希望它至少具有相同的性能。
如果它适合你的内核,你可以从C开始,其值是A吗?这将使内存访问减少33%。也许这适用于你的情况?
__kernel vecadd(__global const float4 *B,
__global float4 *C)
{
int idx = get_global_id(0);
C[idx] += B[idx];
}
另外,你是否厌倦了读取私有向量的值,然后添加?或者两种策略都可以。
__kernel vecadd(__global const float4 *A,
__global const float4 *B,
__global float4 *C)
{
int idx = get_global_id(0);
float4 tmp = A[idx] + B[idx];
C[idx] = tmp;
}