Fast Prefix Sum Implementation Using Subgroups in GLSL Compute Shaders
利用 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模型
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的数据的前缀和
- 拆分成
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) - subgroupInclusiveAdd 计算 32 个 sub_group 内的前缀和,每个 sub_group 的最后一个结果(local_id = 31)存入
shared uint sg_offset[32];(shared 变量在当前 work_group 内共享) - subgroupInclusiveAdd 计算 sg_offset 的前缀和,直接更新到 sg_offset 内,那么
sg_offset[gl_SubgroupSize - 1]即为当前 work_group 的前缀和,结果存入ss_wg_offset_[gl_WorkGroupID.x] - 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的更多相关文章
- 4.4 CUDA prefix sum一步一步优化
1. Prefix Sum 前缀求和由一个二元操作符和一个输入向量组成,虽然名字叫求和,但操作符不一定是加法.先解释一下,以加法为例: 第一行是输入,第二行是对应的输出.可以看到,Output[1] ...
- 牛客多校第十场-D- Rikka with Prefix Sum
链接:https://www.nowcoder.com/acm/contest/148/D来源:牛客网 Prefix Sum is a useful trick in data structure p ...
- 牛客网暑期ACM多校训练营(第十场)D Rikka with Prefix Sum (数学)
Rikka with Prefix Sum 题意: 给出一个数组a,一开始全为0,现在有三种操作: 1. 1 L R W,让区间[L,R]里面的数全都加上W: 2. 2 将a数组变为其前缀 ...
- Rikka with Prefix Sum(组合数学)
Rikka with Prefix Sum 题目描述 Prefix Sum is a useful trick in data structure problems. For example, giv ...
- Rikka with Prefix Sum
Rikka with Prefix Sum 题目 https://www.nowcoder.com/acm/contest/148/D 题目有三个操作 l到r都添加一个数 取一次前缀和 查询区间和 这 ...
- CF1779C Least Prefix Sum 题解
CF链接:Least Prefix Sum Luogu链接:Least Prefix Sum $ {\scr \color {CornflowerBlue}{\text{Solution}}} $ 先 ...
- Codeforces Round #556 (Div. 2) - C. Prefix Sum Primes(思维)
Problem Codeforces Round #556 (Div. 2) - D. Three Religions Time Limit: 1000 mSec Problem Descripti ...
- Codeforces 1485F Copy or Prefix Sum
题目链接 点我跳转 题目大意 给定一个长度为 \(N\) 的序列 \(bi\) 问有多少个长度为 \(N\) 的序列 \(a\) 使得 \(b[i] = a[i]\) 或 \(b[i] = ∑a[j] ...
- 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:// ...
- 牛客网暑期ACM多校训练营(第十场)D Rikka with Prefix Sum (组合数学)
https://www.nowcoder.com/acm/contest/148/D 题意 一个A数组,初始全为0.现有三种操作,1:给区间[L,R]+w:2:把每个位置的元素变为其前缀和:3:求区间 ...
随机推荐
- 日志数据采集-Flume
1. 前言 在一个完整的离线大数据处理系统中,除了hdfs+mapreduce+hive组成分析系统的核心之外,还需要数据采集.结果数据导出.任务调度等不可或缺的辅助系统,而这些辅助工具在hadoop ...
- biancheng-Pygame(python)
http://c.biancheng.net/pygame/ Python Pygame 是一款专门为开发和设计 2D 电子游戏而生的软件包,它支 Windows.Linux.Mac OS 等操作系统 ...
- MySQL---索引、Explain、优化、慢查询
索引 什么是索引? 索引是帮助Mysql提高获取数据的数据结构,换一句话讲就是"排好序的快速查找的数据结构". 一.索引的分类 MySQL主要的几种索引类型:1.普通索引.2.唯 ...
- RSA 小规模演算
原理 秘钥生成 加解密 解密验证 小规模演算
- 薄荷面 Bohemian
我回来了.正如柯洁回到B站. 然后 我将使用知乎格式写作(指换行空一行) 因为<阑山>太长了,有二三十万字,一时半会儿摸不完,同时还在摸几篇短篇小说,还要搞一些什么新概念大赛.冰心作文之类 ...
- Q:oracle通过正则表达式替换对应值
示例 把http://192.168.1.1:8888/a.html中的192.168.1.1:8888/替换成172.32.32.1:9999/ SELECT replace('http://192 ...
- 优化-iceberg调参优化
一.建表优化 1.iceberg表支持更新操作. 文档:https://iceberg.apache.org/docs/latest/configuration/ 功能描述:因v1只支持insert, ...
- centos 8 mysql 更改数据存储位置
登录mysql后,先切换到myql数据库下通过show global variables like '%datadir%'; 可以查看数据默认的存储路径(一般在 /var/lib/mysql) 新建数 ...
- kubernetes 集群中部署 nginx 服务
kubernetes 部署nginx服务 本章节将介绍如何在kubernetes集群中部署一个nginx服务,并且能够对其进行访问. Namespace Namespace是kubernetes系统中 ...
- Linux - 搭建一套Apache大数据集群
一.服务器操作系统 主机名 操作系统 node01 Centos 7.9 node02 Centos 7.9 node03 Centot 7.9 二.大数据服务版本 服务 版本 下载 JDK jdk- ...