我理解矩阵乘法的理论,我对这个特定的内核实现只有两个问题:
作为参考,num_rows = 32.矩阵B(b_mat)之前被另一个内核转换,据我所知,我们将行向量点在一起。
1)为什么我们需要使用参数“vectors_per_row”,从而使用内循环?我以为我们可以做sum + = dot(A行,B行),看起来这个param将行分成更小的部分(为什么?)。
2)我不理解a_mat和b_mat的地址偏移,即a_mat + = start; b_mat + = start * 4;
__kernel void matrix_mult(__global float4 *a_mat,
__global float4 *b_mat, __global float *c_mat) {
float sum;
int num_rows = get_global_size(0);
int vectors_per_row = num_rows/4;
int start = get_global_id(0) * vectors_per_row;
a_mat += start;
c_mat += start*4;
for(int i=0; i<num_rows; i++) {
sum = 0.0f;
for(int j=0; j<vectors_per_row; j++) {
sum += dot(a_mat[j],
b_mat[i*vectors_per_row + j]);
}
c_mat[i] = sum;
}
}
答案 0 :(得分:2)
您的矩阵由一系列float4组成。 Flaoa4是4个浮点数的向量。这就是4来自哪里。 Dot仅适用于内置类型,因此您必须在float4上执行此操作。
c_mat的类型为float,这就是它启动* 4和a_mat启动的原因。偏移是因为代码被分成几个(可能是数百个)线程。每个线程仅计算乘法运算的一小部分。 start
只是线程开始计算的地方。这就是get_global_id(0)的用途。它基本上得到你的线程ID。从技术上讲,它是第一个维度的线程索引,但看起来你只有一个线程维度,所以在这里你可以把它想象成线程id。