Direct3D 12——计算着色器——共享内存与线程同步

每个线程组都有一块称为共享内存(shared memory )或线程本地存储器(thread local storage )的内存空间。这种内存的访问速度很快,可认为与硬件高速缓存的速度不相上下。在我们的计算着色器的代 码中,共享内存的声明如下:

groupshared float4 gCache[256];

数组大小可依用户的需求而定,但是线程组共享内存的上限为32 kb。由于共享内存是线程组里的本地内存,所以要通过SV_GroupThreadID语义对它进行索引。据此,我们可以使组内的每个线程都来访问共享内存中的同一个元素。

使用过多的共享内存会引发性能问题,下面给出例子对此进行详解。假设现有一款最多支 持32 KB 共享内存的多处理器,而用户的计算着色器则需要共享内存20 KB。这意味着只有为每个多处理器设置一个线程组才能满足此限制,因为20 KB + 20 KB = 40 KB >32 KB,所以没有足够的共享内存供另一个线程组使用。这样一来就限制了 GPU的并发性,因为多处理器将无法在多个线程组之间进行切换而屏蔽处理过程中的延迟(建议每个多处理器至少设有两个线程组)。因此, 即使这款硬件在技术上仅支持32 KB的共享内存,但是通过缩减内存的使用量却能令其性能得到优化。

共享内存常见的应用场景是存储纹理数据。在特定的算法中,例如像模糊图像(blur)这种工作,就需要 对同一个纹素进行多次拾取。纹理采样实际上是一种速度较慢的GPU操作,因为内存带宽与内存延迟还未能像GPU的计算能力那样得到极大的改善。但是,我们可以将线程组所需的纹理样本全部预加载至共享内存块,以此来避免密集的纹理拾取操作所带来的性能下滑。接下来,算法流程便会在共享内存块中查 找纹理样本并进行处理,此时的处理速度就很快了。现假设我们以下列有误的代码来实现上述方案:

Texture2D glnput;
RWTexture2D<float4> gOutput;

groupshared float4 gCache[256];

[numthreads(256, 1, 1]
void CS(int3 groupThreadlD : SV_GroupThreadID,int3 dispatchThreadID : SV_DispatchThreadID)
{
    //每个线程都釆集纹理,并将采得的数据存于共享内存中
    gCache[groupThreadID.x] = glnput[dispatchThreadID.xy];
    //接下来执行的计算任务:访问其他线程在共享内存中存储的数据元素
    //糟糕! !!釆集左、右相邻纹素的这两条线程可能还没有完成纹理采样,并且还未将结果存
    //于共享内存中
    float4 left = gCache[groupThreadID.x - 1];
    float4 right = gCache[groupThreadID.x + 1];
    ....
}

有一个问题随之而来,根源在于我们无法保证线程组内的所有线程都能同时完成任务。这可能会导致线程访问到还未经初始化的共享内存元素,因为负责将这些元素进行初始化的相邻线程也许还没有完成它的本职工作。要填上这个坑,就一定要先等待所有的线程都将各自所处理的纹理加载到共享内存之中,而后再令计算着色器继续后面的工作。这时就轮到同步命令闪亮登场了:

Texture2D glnput;
RWTexture2D<float4> gOutput;

[numthreads(256, 1, 1)]
void CS(int3 groupThreadlD : SV_GroupThreadID, int3 dispatchThreadlD : SV_DispatchThreadID)
{
    //每个线程都对纹理进行釆样,再将釆集数据存储在共享内存中
    gCache[groupThreadlD.x] = glnput[dispatchThreadlD.xy];
    //等待组内的所有线程都完成各自的任务
    GroupMemoryBarrierWithGroupSync();
   //此时,读取共享内存的任意元素并执行计算任务都是安全的
   float4 left = gCache[groupThreadlD.x - 1];
   float4 right = gCache[groupThreadlD.x + 1];
  ...
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值