【发布时间】:2021-08-12 05:58:06
【问题描述】:
我有两个向量 a 和 b。每个向量包含一个 3d 点的坐标x、y、zvector3f。
struct Vector3f
{
float x;
float y;
float z;
}
向量a 的大小为n = 5000 点,向量b 的大小为m = 4000。我需要在它们之间做一个张量向量积,就像在图片的右侧一样。结果向量的长度大小应为5000 * 4000,并包含将结果存储在c 的浮点数。
__global__ void tensor3dProdcutClassic(const int n, const int m, const Vector3f *a, const Vector3f *b, float *c) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
// int j = blockIdy.y * blockDim.y + threadIdx.y;
//check if the idx is out of range
if (i < n) {
for (int j = 0; j < m; j++) {
int idx = j + m * i;
c[idx] = a[i].x * b[j].x + a[i].y * b[j].y + a[i].z * b[j].z;
}
}
}
dim3 blockSize(32, 1, 1);
dim3 gridSize((n + blockSize.x - 1) / blockSize.x, 1, 1);
tensor3dProdcutClassic<<<gridSize, blockSize>>>(n, m, x, y, out);
我在 Volta 拱门上得到了很长的执行时间。
我的问题是如何优化内核以减少时间,这主要是因为内核内部的 for 循环。我知道这里所有的全局读写都没有合并。
【问题讨论】:
-
如果你想获得高性能,那么使用数组结构是一个非常糟糕的主意,尤其是在基于 SIMT 模型的 GPU 上。请注意,由于字段数不能被 2 的幂整除,因此对齐可能会成为问题。
-
谢谢你,理查德,你是对的。我已将 Vector3f 更改为 typedef float Point3d[3];但我仍然得到很高的计算时间
-
问题不在于结构本身,而在于内存布局。尽管 3 个浮点数的数组在可能的填充与否方面可能会更好,但它仍然会导致低效的交错读取。我正在考虑拥有 3 个普通的大数组 (x + y + z)。
-
同意,定义 3 个普通数组或将它们存储在以行优先顺序的矩阵中可以提供更好的性能并提供有效的交错读取。我将修改代码。然而,主要问题是内核实现没有优化,因此速度很慢。