← [Back to Twitter thread index](../README.md) --- 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