利用 Vulkan 1.1 的 subgroup 特性加速 ComputeShader 的前缀和计算,参考:

Vulkan Subgroup Tutorial - Khronos Blog - The Khronos Group Inc

Single-pass Parallel Prefix Scan with Decoupled Look-back | Research

相关知识

Compute模型

flowchart TD
subgraph Subgroup["Subgroup"]
Inv0["invocation 0"]
Inv1["invocation 1"]
InvDots["..."]
Inv31["invocation 31"]
end
subgraph Workgroup["Workgroup"]
SG0["Subgroup 0"]
SG1["Subgroup 1"]
SGDots["..."]
SGM["Subgroup m"]
end
subgraph Dispatch["Dispatch"]
WG0["Workgroup 0"]
WG1["Workgroup 1"]
WGDots["..."]
WGN["Workgroup n"]
end

%% 设置水平排
WG0 --- WG1 --- WGDots --- WGN
SG0 --- SG1 --- SGDots --- SGM
Inv0 --- Inv1 --- InvDots --- Inv31

shared memory

shared 变量在单个 work group 内共享,本文用于记录多个 subgroup 的前缀和结果

subgroup

GPU 上,线程通常以小组(通常为 32 或 64 个线程)的形式执行,本文利用 subgroupInclusiveAdd 计算单个 subgroup 内的前缀和,具体参考 https://www.khronos.org/blog/vulkan-subgroup-tutorial

假设有8个块,其active状态如下

id : 0  1  2  3  4  5  6  7
val: 0 1 0 1 1 0 0 1
//subgroupInclusiveAdd
val: 0 1 1 2 3 3 3 4

流程概要

目标:计算size = n的数据的前缀和

  1. 拆分成 work_group_nums = (n + 1023) / 1024 个 local_size = <1024, 1, 1>的 work_group 的前缀和,一个 work_group 有 1024 个 invocation,1024 个 invocation 拆分成 32 个 sub_group 的前缀和 (sub_group_size = 32 on NIVDIA)
  2. subgroupInclusiveAdd 计算 32 个 sub_group 内的前缀和,每个 sub_group 的最后一个结果(local_id = 31)存入 shared uint sg_offset[32]; (shared 变量在当前 work_group 内共享)
  3. subgroupInclusiveAdd 计算 sg_offset 的前缀和,直接更新到 sg_offset 内,那么 sg_offset[gl_SubgroupSize - 1] 即为当前 work_group 的前缀和,结果存入 ss_wg_offset_[gl_WorkGroupID.x]
  4. final pass 对 ss_wg_offset_ 再做一次前缀和,由于单位已经不是 work_group 内的 invocation,subgroupInclusiveAdd 无法 group 工作,于是手动遍历累加写入atomicExchange(ss_wg_offset_[gl_WorkGroupID.x], final_res);

实现细节

layout(local_size_x = 1024, local_size_y = 1, local_size_z = 1) in;
//shared memory跨subgroup暂存结果
shared uint sg_offset[32]; //sub_group_id
uint sg_id = gl_LocalInvocationIndex / gl_SubgroupSize; // 前一个块是否有活跃voxel
uint prev_inv_actives = invocationActives(gl_GlobalInvocationID.x - 1) > 0 ? 1 : 0;
// sub_group 内的前缀和
uint wg_offset = subgroupInclusiveAdd(prev_inv_actives);
// sg_offset 存储32个 sub_group 最后的前缀和
if (gl_SubgroupInvocationID == gl_SubgroupSize-1) {
sg_offset[sg_id] = wg_offset;
} barrier(); if (sg_id == 0) {
// 对 sg_offset 计算一次前缀和,直接更新到 sg_offset 内
sg_offset[gl_SubgroupInvocationID] =
subgroupInclusiveAdd(sg_offset[gl_SubgroupInvocationID]);
// 结果存入 ss_wg_offset_, 省略ecnode过程
atomicExchange(ss_wg_offset_[gl_WorkGroupID.x], your_value_encode);
} barrier(); // 简单的 final pass, 省略 barrier();

tips: GLSL没有提供 atomicRead,可以通过 atomicCompSwap(target, 0, 0) 实现

Fast Prefix Sum Implementation Using Subgroups in GLSL Compute Shaders的更多相关文章

  1. 4.4 CUDA prefix sum一步一步优化

    1. Prefix Sum 前缀求和由一个二元操作符和一个输入向量组成,虽然名字叫求和,但操作符不一定是加法.先解释一下,以加法为例: 第一行是输入,第二行是对应的输出.可以看到,Output[1] ...

  2. 牛客多校第十场-D- Rikka with Prefix Sum

    链接:https://www.nowcoder.com/acm/contest/148/D来源:牛客网 Prefix Sum is a useful trick in data structure p ...

  3. 牛客网暑期ACM多校训练营(第十场)D Rikka with Prefix Sum (数学)

    Rikka with Prefix Sum 题意: 给出一个数组a,一开始全为0,现在有三种操作: 1.  1 L R W,让区间[L,R]里面的数全都加上W: 2.  2     将a数组变为其前缀 ...

  4. Rikka with Prefix Sum(组合数学)

    Rikka with Prefix Sum 题目描述 Prefix Sum is a useful trick in data structure problems. For example, giv ...

  5. Rikka with Prefix Sum

    Rikka with Prefix Sum 题目 https://www.nowcoder.com/acm/contest/148/D 题目有三个操作 l到r都添加一个数 取一次前缀和 查询区间和 这 ...

  6. CF1779C Least Prefix Sum 题解

    CF链接:Least Prefix Sum Luogu链接:Least Prefix Sum $ {\scr \color {CornflowerBlue}{\text{Solution}}} $ 先 ...

  7. Codeforces Round #556 (Div. 2) - C. Prefix Sum Primes(思维)

    Problem  Codeforces Round #556 (Div. 2) - D. Three Religions Time Limit: 1000 mSec Problem Descripti ...

  8. Codeforces 1485F Copy or Prefix Sum

    题目链接 点我跳转 题目大意 给定一个长度为 \(N\) 的序列 \(bi\) 问有多少个长度为 \(N\) 的序列 \(a\) 使得 \(b[i] = a[i]\) 或 \(b[i] = ∑a[j] ...

  9. A Fast Priority Queue Implementation of the Dijkstra Shortest Path Algorithm

    http://www.codeproject.com/Articles/24816/A-Fast-Priority-Queue-Implementation-of-the-Dijkst http:// ...

  10. 牛客网暑期ACM多校训练营(第十场)D Rikka with Prefix Sum (组合数学)

    https://www.nowcoder.com/acm/contest/148/D 题意 一个A数组,初始全为0.现有三种操作,1:给区间[L,R]+w:2:把每个位置的元素变为其前缀和:3:求区间 ...

随机推荐

  1. linux:用户管理

    用户账号添加.删除.修改以及用户密码的管理 用户组的管理 涉及三个文件: /etc/passwd    :存储用户的关键信息 /etc/group :存储用户组的关键信息 /etc/shadow :存 ...

  2. try-catch-finally的使用

    /* * 一.异常的处理:抓抛模型 * * 过程一:"抛":程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象. * 并将此对象抛出. * 一旦抛出对象 ...

  3. EMWIN图形库入门

    一.EMWIN图形库移植 在STM32ZET6(64KB SRAM.512KB FLASH)上移植,参考正点原子STM32F1 EMWIN开发手册_V2.0 STemWin源码可以在ST官网下载 版本 ...

  4. Binomial Sum 学习笔记

  5. Flink同步mysql写入Iceberg异常,一秒写入一次

    1.现象 在Iceberg数据湖治理过程中发现,同步任务运行7天没有写入数据,运行7天后突然大批量产生Commit,一秒产生一个Commit. 2.问题 Flink写入checkpoint时会在che ...

  6. Map模糊搜索key

    一.代码 public class StringTest { public static void main(String[] args) { Map<String, Object>map ...

  7. Maven配置多数据源

    一.配置文件 修改maven配置文件,用户目录下.m2文件夹中的setting.xml,内容如下 <?xml version="1.0" encoding="UTF ...

  8. Leetcode 765 情侣牵手 / Hetao-013 翅膀打结 题解 [ 黄 ] [ 并查集 ] [ BFS ] [ 贪心 ]

    经典的连通块题,幸好我之前在 leetcode 看过原. 转化 首先观察到一对cp无论是男在前,还是女在前,都视为配对成功,对答案无影响. 因此,我们可以把一对情侣赋同一个编号,直接加一除以二即可. ...

  9. 一键部署+限免体验!盘点如何在华为云上体验DeepSeek

    本文分享自华为云社区<一键部署+限免体验!盘点如何在华为云上体验DeepSeek>,作者:华为云社区精选. 还在为DeepSeek深度思考出现"服务器繁忙"而头疼?华为 ...

  10. 干货:DeepSeek+SpringAI实现流式对话!

    前面一篇文章我们实现了<炸裂:SpringAI内置DeepSeek啦!>,但是大模型的响应速度通常是很慢的,为了避免用户用户能够耐心等待输出的结果,我们通常会使用流式输出一点点将结果输出给 ...