docs(twitter): add 1588906002212323328 corpus (NOTimothyLottes GPU Programming Tip Line, Nov 2022)

21-post thread, 0 media, 20 numbered GPU tips - the earliest
NOTimothyLottes thread in the corpus. Highlights:
[0] Normalization 'rsq(0)=INF*0=NaN' -> 'normalize_safe(x){return x*min(MAX_FLOAT,rsq(dot(x,x)));}'
[1] FP16 1/denormals -> INFs -> NaNs; fix 'rcp(max(x,SMALLEST_NORMAL))'
[2] 'spirv-opt -Os' against IHV compile times
[3] Driver ignoring '[[dont_unroll]]' workaround via constantBuffer.zero
[4-5] 'Ship-One-Shader' = one SPIR-V binary + specialization constants at PSO gen (requires spirv-opt -Os)
[6-8] Bit masking: signed 'bitfieldExtract(int(v),bit,1)' to all-0/1 mask; AMD 'Bfi' as '(ins&mask)|(src&(~mask))'; bitfieldInsert hits V_BFI_B32 portable
[9] clamp = med3 on AMD (V_MED3_* non-portable)
[10-11] Bool-as-float: 'saturate(a*b+c)' for AND|OR, '(-a)*b+1.0' for NAND
[12] INF-to-NaN: 'x*0.0+x'
[13-15] Semi-persistent workgroups (4x 8x8 tiles in 16x16 footprint, 64-wide group) - up to 10% perf on AMD, gains via L0 retention, no wait-for-store on exit
[16-17] Merge passes to avoid DRAM round-trips; serial dependent passes can be merged into one shader for >10% L2-resident gains
[18-19] Packed 16-bit double-rate: up to 30% (except NV); even without, 16-bit manages register pressure esp with smaller HW limits or compiler troubles
This commit is contained in:
ed
2026-07-27 02:00:58 -04:00
parent eed1590d1e
commit 5db46d3b64
2 changed files with 441 additions and 0 deletions
@@ -0,0 +1,99 @@
---
title: "[19] Even without double rate 16-bit, 16-bit is the most important tool for mana"
author: "NOTimothyLottes"
handle: "@NOTimothyLottes"
post_url: "https://x.com/NOTimothyLottes/status/1588906002212323328"
post_id: "1588906002212323328"
timestamp: "2022-11-05 14:48:06"
post_count: 21
reply_count: 0
repost_count: 0
like_count: 0
view_count: 0
---
# @NOTimothyLottes — [19] Even without double rate 16-bit, 16-bit is the most important tool for mana
## Post 1 (2022-11-05 14:32:31)
GPU Programming Tip Line Thread /
## Post 2 (2022-11-05 14:32:57) — reply to Post 1
[0] Normalization fail case is 'rsq(0)=INF*0=NaN', trim out intermediate INF to fix, 'normalize_safe(x){return x*min(MAX_FLOAT,rsq(dot(x,x)));}'
## Post 3 (2022-11-05 14:34:35) — reply to Post 2
[1] PC FP16 1/denormals generates INFs which can easily eventually result in NaNs, fix positives with 'rcp(max(x,SMALLEST_NORMAL))'
## Post 4 (2022-11-05 14:36:40) — reply to Post 3
[2] 'spirv-opt -Os' (optimize for size) is your weapon against "back-before-its-done--getting-groceries" IHV compile times
## Post 5 (2022-11-05 14:37:40) — reply to Post 4
[3] Driver ignoring your '[[dont_unroll]]', 'int eatThisBuddy=1+/*hidden-zero*/constantBuffer.zero[0];for(i=0;i<1024;i+=eatThisBuddy){...'
## Post 6 (2022-11-05 14:38:30) — reply to Post 5
[4] 'Ship-One-Shader' = One SPIR-V binary, use specialization constants to select shader at PSO generation time, minimizes released shader binary size
## Post 7 (2022-11-05 14:38:48) — reply to Post 6
[5] 'Ship-One-Shader' requires 'spirv-opt -Os'
## Post 8 (2022-11-05 14:39:03) — reply to Post 7
[6] Use signed 'mask=bitfieldExtract(int(v),bit,1)' to turn bit into all 0's or 1's mask
## Post 9 (2022-11-05 14:39:51) — reply to Post 8
[7] On PC for AMD's native V_BFI_B32 (to select bits based on mask) use 'Bfi(int src,int ins,int mask){return (ins&mask)|(src&(~mask));}'
## Post 10 (2022-11-05 14:40:11) — reply to Post 9
[8] Use 'bitfieldInsert(,,0,compileTimeImmediate)' hits fast V_BFI_B32 on AMD, and portable to other vendors
## Post 11 (2022-11-05 14:40:48) — reply to Post 10
[9] AMD ONLY: clamp(a,b,c) is implemented as med3(a,b,c), so can get V_MED3_* without an extension (in a non-portable way)
## Post 12 (2022-11-05 14:41:10) — reply to Post 11
[10] Bools as 0|1 floats '(a&b)|c' can be done via 'saturate(a*b+c)'
## Post 13 (2022-11-05 14:41:26) — reply to Post 12
[11] Bools as 0|1 floats '!(a&b)' can be done via '(-a)*b+1.0'
## Post 14 (2022-11-05 14:41:52) — reply to Post 13
[12] Convert INFs to NaNs via 'x*0.0+x'
## Post 15 (2022-11-05 14:43:41) — reply to Post 14
[13] Semi-persistent workgroup opt = reusing the workgroup for more work before exit (ie processing four 8x8 tiles in a 16x16 footprint using a 64-wide group)
## Post 16 (2022-11-05 14:44:49) — reply to Post 15
[14] Semi-persistent workgroups can be good for up to 10% perf on AMD (YMMV) ... assuming compiler doesn't fail VGPR allocation, check your disassembly
## Post 17 (2022-11-05 14:45:15) — reply to Post 16
[15] Semi-persistent workgroups gain by keeping more local work on the same L0, by factoring out wait for store on wave exit, and better scheduling
## Post 18 (2022-11-05 14:45:27) — reply to Post 17
[16] Merge passes to avoid round trip through DRAM, often huge wins there
## Post 19 (2022-11-05 14:46:04) — reply to Post 18
[17] Sometimes serial dependent passes can be merged into one shader to keep work in L2 for >10% gains, requires "unsafe you-shouldnt-do-that" logic that works
## Post 20 (2022-11-05 14:47:09) — reply to Post 19
[18] Proper double rate "packed" 16-bit can provides gains up to 30% depending on workload/platform (except NV)
## Post 21 (2022-11-05 14:48:06) — reply to Post 20
[19] Even without double rate 16-bit, 16-bit is the most important tool for managing register pressure problems, esp with smaller HW register limits or compiler troubles
@@ -0,0 +1,342 @@
{
"root_post_id": "1588906002212323328",
"posts": [
{
"post_id": "1588902081502797826",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "GPU Programming Tip Line Thread /",
"timestamp": "2022-11-05 14:32:31",
"media_urls": [],
"reply_to_id": null,
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 6,
"view_count": 0
}
},
{
"post_id": "1588902190034620417",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[0] Normalization fail case is 'rsq(0)=INF*0=NaN', trim out intermediate INF to fix, 'normalize_safe(x){return x*min(MAX_FLOAT,rsq(dot(x,x)));}'",
"timestamp": "2022-11-05 14:32:57",
"media_urls": [],
"reply_to_id": "1588902081502797826",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588902600686329857",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[1] PC FP16 1/denormals generates INFs which can easily eventually result in NaNs, fix positives with 'rcp(max(x,SMALLEST_NORMAL))'",
"timestamp": "2022-11-05 14:34:35",
"media_urls": [],
"reply_to_id": "1588902190034620417",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588903127549607936",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[2] 'spirv-opt -Os' (optimize for size) is your weapon against \"back-before-its-done--getting-groceries\" IHV compile times",
"timestamp": "2022-11-05 14:36:40",
"media_urls": [],
"reply_to_id": "1588902600686329857",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588903378952007680",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[3] Driver ignoring your '[[dont_unroll]]', 'int eatThisBuddy=1+/*hidden-zero*/constantBuffer.zero[0];for(i=0;i<1024;i+=eatThisBuddy){...'",
"timestamp": "2022-11-05 14:37:40",
"media_urls": [],
"reply_to_id": "1588903127549607936",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588903586721042432",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[4] 'Ship-One-Shader' = One SPIR-V binary, use specialization constants to select shader at PSO generation time, minimizes released shader binary size",
"timestamp": "2022-11-05 14:38:30",
"media_urls": [],
"reply_to_id": "1588903378952007680",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588903663468437508",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[5] 'Ship-One-Shader' requires 'spirv-opt -Os'",
"timestamp": "2022-11-05 14:38:48",
"media_urls": [],
"reply_to_id": "1588903586721042432",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588903725783220224",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[6] Use signed 'mask=bitfieldExtract(int(v),bit,1)' to turn bit into all 0's or 1's mask",
"timestamp": "2022-11-05 14:39:03",
"media_urls": [],
"reply_to_id": "1588903663468437508",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588903926510014467",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[7] On PC for AMD's native V_BFI_B32 (to select bits based on mask) use 'Bfi(int src,int ins,int mask){return (ins&mask)|(src&(~mask));}'",
"timestamp": "2022-11-05 14:39:51",
"media_urls": [],
"reply_to_id": "1588903725783220224",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588904013239844870",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[8] Use 'bitfieldInsert(,,0,compileTimeImmediate)' hits fast V_BFI_B32 on AMD, and portable to other vendors",
"timestamp": "2022-11-05 14:40:11",
"media_urls": [],
"reply_to_id": "1588903926510014467",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588904166269005824",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[9] AMD ONLY: clamp(a,b,c) is implemented as med3(a,b,c), so can get V_MED3_* without an extension (in a non-portable way)",
"timestamp": "2022-11-05 14:40:48",
"media_urls": [],
"reply_to_id": "1588904013239844870",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588904259265114112",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[10] Bools as 0|1 floats '(a&b)|c' can be done via 'saturate(a*b+c)'",
"timestamp": "2022-11-05 14:41:10",
"media_urls": [],
"reply_to_id": "1588904166269005824",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588904325543493633",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[11] Bools as 0|1 floats '!(a&b)' can be done via '(-a)*b+1.0'",
"timestamp": "2022-11-05 14:41:26",
"media_urls": [],
"reply_to_id": "1588904259265114112",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588904434268262400",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[12] Convert INFs to NaNs via 'x*0.0+x'",
"timestamp": "2022-11-05 14:41:52",
"media_urls": [],
"reply_to_id": "1588904325543493633",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588904891707424768",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[13] Semi-persistent workgroup opt = reusing the workgroup for more work before exit (ie processing four 8x8 tiles in a 16x16 footprint using a 64-wide group)",
"timestamp": "2022-11-05 14:43:41",
"media_urls": [],
"reply_to_id": "1588904434268262400",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588905179449282560",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[14] Semi-persistent workgroups can be good for up to 10% perf on AMD (YMMV) ... assuming compiler doesn't fail VGPR allocation, check your disassembly",
"timestamp": "2022-11-05 14:44:49",
"media_urls": [],
"reply_to_id": "1588904891707424768",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588905286697639936",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[15] Semi-persistent workgroups gain by keeping more local work on the same L0, by factoring out wait for store on wave exit, and better scheduling",
"timestamp": "2022-11-05 14:45:15",
"media_urls": [],
"reply_to_id": "1588905179449282560",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588905339122257921",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[16] Merge passes to avoid round trip through DRAM, often huge wins there",
"timestamp": "2022-11-05 14:45:27",
"media_urls": [],
"reply_to_id": "1588905286697639936",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588905491027341312",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[17] Sometimes serial dependent passes can be merged into one shader to keep work in L2 for >10% gains, requires \"unsafe you-shouldnt-do-that\" logic that works",
"timestamp": "2022-11-05 14:46:04",
"media_urls": [],
"reply_to_id": "1588905339122257921",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588905764005216258",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[18] Proper double rate \"packed\" 16-bit can provides gains up to 30% depending on workload/platform (except NV)",
"timestamp": "2022-11-05 14:47:09",
"media_urls": [],
"reply_to_id": "1588905491027341312",
"quote_of_id": null,
"metrics": {
"reply_count": 1,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
},
{
"post_id": "1588906002212323328",
"author": "NOTimothyLottes",
"handle": "NOTimothyLottes",
"text": "[19] Even without double rate 16-bit, 16-bit is the most important tool for managing register pressure problems, esp with smaller HW register limits or compiler troubles",
"timestamp": "2022-11-05 14:48:06",
"media_urls": [],
"reply_to_id": "1588905764005216258",
"quote_of_id": null,
"metrics": {
"reply_count": 0,
"repost_count": 0,
"like_count": 0,
"view_count": 0
}
}
],
"source_url": "https://x.com/NOTimothyLottes/status/1588906002212323328"
}