大型数据集的 Vulkan 重叠计算操作和内存访问

Vulkan Overlapping Compute Operations with Memory-Access for large datasets

这是 的延续。

不过这次我没有超出设备限制。所以我得到了一个 存储缓冲区 ,其中填充了一些初始数据,并将其附加到一个着色器,该着色器在同一存储缓冲区中执行读取增量存储。

void main() {
    data[i] += data[i]
}

所以只看这个会不会有任何同步问题?我没看到,每个 PE 都在用自己的数据进行计算。

有趣的是,从输出来看,就值而言,它看起来像一个 sin 函数,从 0 开始,然后 0 =31=]1 然后 0,缓冲区开头的值自乘几次,进入缓冲区越多,到达中间在价值被自己乘以很多次的地方,然后我们到达最终价值被自己乘以的次数越来越少。缓冲区中存在的所有值都是初始值的倍数

有人说 GPU 通过将计算操作与内存访问重叠来隐藏内存延迟。但是,什么样的重叠会破坏我的所有数据?

还有些人注意到 vkDispatch(x,y,z) x,y,z 值在某种程度上充当乘数,如果我只在 x 上派遣我明白了更少出错的输出数据,仍然不应该发生,对于大型数据集,我确实达到了设备的极限,所以我该怎么办? → 我分别在 yz 开始调度,然后当我这样做时,我会看到更容易出错的结果。

如果您有 N 个项目,并且最大调度宽度 (x) 为 MaxX,您想要执行如下操作:

int x = N > MaxX ? MaxX : N;
int y = N / MaxX;
if (y * MaxX < N)
    y++; // round up when N isn't an integer multiple of MaxX
vkCmdDispatch(cmdbuf, x, y, 1);

然后在你的着色器中:

int dispatch_x = gl_WorkGroupSize.x * gl_NumWorkGroups.x;
int i = (gl_GlobalInvocationID.y * dispatch_x) + gl_GlobalInvocationID.x;
// number of invocations might be greater than N either because
// N doesn't divide into the workgroup size evenly, or because N
// doesn't divide into dispatch_x evenly (or both).
if (i >= N) return;
data[i] += data[i];