OpenCL标量与矢量

时间:2012-01-19 21:23:43

标签: opencl gpu gpgpu

我有简单的内核:

__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),矢量化版本更快,但我想知道,为什么?

2 个答案:

答案 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;
}