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:求区间 ...
随机推荐
- MongoDB:使用场景简介
- 面向对象(下)的阶段性复习:关键字abstract、模板方法的设计模式、关键字interface、代理模式、工厂的设计模式、类的结构内部类
关键字:abstract abstract: 抽象的1.可以用来修饰:类.方法2.具体的:abstract修饰类:抽象类 * > 此类不能实例化 * > 抽象类中一定有构造器,便于子类实例 ...
- 恭喜我同事的论文被IEEE HPCC收录!
近日,由天翼云科技有限公司云网产品事业部天玑实验室撰写的<关于公有云区分负载QoS感知的内存资源动态超分管理优化>(Thoth:Provisioning Overcommitted Mem ...
- Layer子域名挖掘机
Layer子域名挖掘机 Layer子域名挖掘机是一款功能强大的域名查询工具,主要用于提供网站子域名的查询服务. 域名与子域名 域名 域名,又称网域,是互联网上用于标识特定计算机或计算机组的一串由点分隔 ...
- 流程控制之for循环练习画三角形
package com.yeyue.struct; public class TestDemo { public static void main(String[] args) { //打印三角形 5 ...
- IPMITool 工具使用详细教程
IPMITool 工具使用详细教程 一.IPMI 与 IPMITool 简介 1. IPMI 概述 智能平台管理接口(Intelligent Platform Management Interface ...
- ES - 概述
前言 Q1:ElasticSearch 是什么? 为什么要学习? ElasticSearch 是一个分布式.可扩展.实时的搜索和分析引擎,基于 Lucene 构建.它可以用于全文搜索.结构化搜索.分析 ...
- 如何学好.net core?
https://www.zhihu.com/question/348740859/answer/842656513
- GUI图形界面编程(Java)
GUI编程 组件 窗口 弹窗 面板 文本框 列表框 按钮 图片 监听事件 鼠标 键盘事件 破解工具 1.简介 Gui的核心技术:Swing.AWT 2.AWT 2.1.AWT介绍 1.包含了很多类和接 ...
- 万字长文手把手教你实现MicroPython/Python发布第三方库
MicroPython/Python 发布第三方库 原文链接: FreakStudio的博客 摘要 文章讲解内容包括第三方库文件说明和组织.开源许可协议选择.通过black模块.Flake8模块和预提 ...