diff --git a/docs/twitter/1588906002212323328/thread.md b/docs/twitter/1588906002212323328/thread.md new file mode 100644 index 00000000..e6e9bb2a --- /dev/null +++ b/docs/twitter/1588906002212323328/thread.md @@ -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 diff --git a/docs/twitter/1588906002212323328/thread_data.json b/docs/twitter/1588906002212323328/thread_data.json new file mode 100644 index 00000000..280b58fc --- /dev/null +++ b/docs/twitter/1588906002212323328/thread_data.json @@ -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" +} \ No newline at end of file