具有内存合并的OpenCl矩阵转置

时间:2014-08-19 00:23:39

标签: opencl gpu coalescing

我目前正试图在内存中使用内存合并来转置Matrix。

我已经以“简单”的方式对Matrix进行了彻底的处理。当我现在尝试使用内存合并做同样的事情时,我希望看到执行时间略有改进,但我的实现实际上比简单实现慢(实现是正确的,它只是没有效率)。我想我还没有完全理解如何确保水平相邻的工作项写在水平相邻的地址上。

这是我的煤矿实施的核心:

__kernel void MatrixTranspose(__global const float* Matrix, 
__global float* MatrixTransposed, uint Width, uint Height, __local float* block) {

    int2 GlobalID;
    GlobalID.x = get_global_id(0);
    GlobalID.y = get_global_id(1);

    int2 LocalID;
    LocalID.x = get_local_id(0);
    LocalID.y = get_local_id(1);

    block[LocalID.y*get_local_size(0) + LocalID.x] = Matrix[GlobalID.y*Width + GlobalID.x];

    barrier(CLK_LOCAL_MEM_FENCE);

    int2 groupId;
    groupId.x = get_group_id(0);
    groupId.y = get_group_id(1);
    int2 localSize;
    localSize.x = get_local_size(0);
    localSize.y = get_local_size(1);
    MatrixTransposed[Height*(LocalID.x + groupId.x*localSize.x) + Height - (LocalID.y + groupId.y*localSize.y) - 1] = block[LocalID.y*localSize.x + LocalID.x];
}

我希望有人可以给我一个建议,谢谢你:)。

2 个答案:

答案 0 :(得分:2)

不幸的是,您将受到设备全局读写速度的限制。通常,您可以转置矩阵进行一些计算,这有助于隐藏延迟。您正在阅读本地内存,等待屏障,并在示例中将黑色写入全局。这只会增加使用本地内存的额外步骤和复杂性。

如果要隐藏全局内存延迟,则应该在本地内存中对数据执行某些操作。

如果您只想转置矩阵,只需从全局读取并直接写入全局目标位置即可。如果您仍想尝试使用本地内存,也可以查看async_work_group_copy。

现在回答我的问题。

尝试使工作项负责多个浮动。如果您使用工作项读取4x4区域,则可以将其转置到私有内存中。这不仅可以跳过本地内存,而且可以消除对屏障的需求,并将所需的工作项数量减少16倍。

步骤进行:

  • 计算src和dest全局内存地址
  • 从全局
  • 加载四个float4值
  • 通过相应地交换w,x,y,z值来转换4x4浮点数
  • 在全局内存中的新位置存储4个float4值
  • 在单独的内核中处理矩阵的边缘区域,或者在主程序中处理具有非四个维度的矩阵(或填充输入矩阵以使其为4的倍数)

答案 1 :(得分:1)

从原始矩阵中读取列,将它们作为行写入本地内存以避免内存库冲突,然后将本地内存中的行存储到转置矩阵中。

在这种情况下,两个写操作很容易合并(邻居工作项写入邻居存储单元)。然而,读操作并不是那么好。

是的,你的设备是什么?如果使用向量操作很好,请使用vload / vstore操作,这可能会显着提高IO性能。