从样本中获取的代码。我用它创建了一个项目并且它可以工作,但我不了解某些部分。
为了示例,假设我有一个32x32矩阵,有36个工作项,因此get_global_id(0)从0开始 - > 35我猜想,大小= MATRIX_DIM / 4 = 8。
__kernel void transpose(__global float4 *g_mat,
__local float4 *l_mat, uint size) {
__global float4 *src, *dst;
/* Determine row and column location */
int col = get_global_id(0);
int row = 0;
while(col >= size) {
col -= size--;
row++;
}
col += row;
size += row;
/* Read source block into local memory */
src = g_mat + row * size * 4 + col;
l_mat += get_local_id(0)*8;
在clEnqueueNDRangeKernel
调用中,arg local_work_size
设置为NULL
,根据手册的意思,让编译器或其他东西弄清楚:
local_work_size can also be a NULL value in which case the OpenCL implementation will determine how to be break the global work-items into appropriate work-group instances.
但我不明白乘以8,这给我的工作组的本地内存提供了一个地址偏移量。有人可以解释一下吗?
l_mat[0] = src[0];
l_mat[1] = src[size];
l_mat[2] = src[2*size];
l_mat[3] = src[3*size];
/* Process block on diagonal */
if(row == col) {
src[0] =
(float4)(l_mat[0].x, l_mat[1].x, l_mat[2].x, l_mat[3].x);
src[size] =
(float4)(l_mat[0].y, l_mat[1].y, l_mat[2].y, l_mat[3].y);
src[2*size] =
(float4)(l_mat[0].z, l_mat[1].z, l_mat[2].z, l_mat[3].z);
src[3*size] =
(float4)(l_mat[0].w, l_mat[1].w, l_mat[2].w, l_mat[3].w);
}
/* Process block off diagonal */
else {
/* Read destination block into local memory */
dst = g_mat + col * size * 4 + row;
l_mat[4] = dst[0];
l_mat[5] = dst[size];
l_mat[6] = dst[2*size];
l_mat[7] = dst[3*size];
/* Set elements of destination block */
dst[0] =
(float4)(l_mat[0].x, l_mat[1].x, l_mat[2].x, l_mat[3].x);
dst[size] =
(float4)(l_mat[0].y, l_mat[1].y, l_mat[2].y, l_mat[3].y);
dst[2*size] =
(float4)(l_mat[0].z, l_mat[1].z, l_mat[2].z, l_mat[3].z);
dst[3*size] =
(float4)(l_mat[0].w, l_mat[1].w, l_mat[2].w, l_mat[3].w);
/* Set elements of source block */
src[0] =
(float4)(l_mat[4].x, l_mat[5].x, l_mat[6].x, l_mat[7].x);
src[size] =
(float4)(l_mat[4].y, l_mat[5].y, l_mat[6].y, l_mat[7].y);
src[2*size] =
(float4)(l_mat[4].z, l_mat[5].z, l_mat[6].z, l_mat[7].z);
src[3*size] =
(float4)(l_mat[4].w, l_mat[5].w, l_mat[6].w, l_mat[7].w);
}
}
答案 0 :(得分:1)
l_mat 用作临时缓冲区,用于存储要反转所有工作项的两个矩阵组件。
因此,对于每个工作项,它需要存储 2 * 4 float4s,因此: offset = get_local_id(0)* 2 * 4 = get_local_id(0)* 8
答案 1 :(得分:1)
l_mat
被用作工作组中线程的本地存储。具体来说,它被使用是因为对本地存储器的访问比全局存储器快几个数量级。
每个帖子需要8 float4
秒。执行以下指针算法
l_mat += get_local_id(0)*8;
为每个线程移动l_mat
指针,使其不与其他线程的数据重叠。
此可能导致错误,因为未指定local_size,我们无法确保l_mat
的大小足以存储每个线程的值。