code wiki / (root) / nx_conv_bwd_stride_gate.nx

nx_conv_bwd_stride_gate.nx source

↩ module page · 46 lines · 2891 B

1// nx_conv_bwd_stride_gate.nx -- EXACT check of nx_f32_conv2d_backward at STRIDE 2 (only stride-1 was gated before; 2// the student-distill collapse pointed here). 4x4 input=[1..16], 2x2 weight, stride 2 pad 0 -> 2x2 out; dOut=all-1 3// -> dW[kh,kw] = sum over the 2x2 output of in(oh*2+kh, ow*2+kw): dW=[24,28,40,44] (hand-computed). expect_exit: 0 4import "nx_syscalls.nx" 5import "nx_f32_cvt.nx" 6import "nx_f32_conv2d.nx" 7import "nx_f32_conv2d_backward.nx" 8 9func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return sys_write(1,s,n) } 10func gn(v: i64) -> i64 { let bb:*u8=sys_mmap(28); var m:i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} let t:*u8=sys_mmap(28); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i:i64=0; while i<k{bb[i]=t[k-1-i];i=i+1} return sys_write(1,bb,k) } 11 12func main(argc: i64, argv: *i64) -> i64 { 13 var pass: i64 = 0 14 let input: *i64=sys_mmap(8*16) as *i64 15 let W: *i64=sys_mmap(8*4) as *i64 16 let dout: *i64=sys_mmap(8*4) as *i64 17 let dinput: *i64=sys_mmap(8*16) as *i64 18 let dW: *i64=sys_mmap(8*4) as *i64 19 let dB: *i64=sys_mmap(8) as *i64 20 var i: i64=0; while i<16 { input[i]=nx_i32_to_f32(i+1); i=i+1 } 21 W[0]=nx_i32_to_f32(1); W[1]=nx_i32_to_f32(1); W[2]=nx_i32_to_f32(1); W[3]=nx_i32_to_f32(1) 22 i=0; while i<4 { dout[i]=nx_i32_to_f32(1); i=i+1 } 23 24 // stride 2, pad 0: OH=OW=2 25 let rc: i64=nx_f32_conv2d_backward(input,1,1,4,4, W,1,2,2, 2,0, dout, dinput, dW, dB) 26 // S1 dW = [24,28,40,44] 27 if dW[0]==nx_i32_to_f32(24) { if dW[1]==nx_i32_to_f32(28) { if dW[2]==nx_i32_to_f32(40) { if dW[3]==nx_i32_to_f32(44) { 28 pass=pass+1; gp("S1 stride-2 dW=[24,28,40,44] exact OK\n" as *u8) 29 } } } } 30 if dW[0]!=nx_i32_to_f32(24) { gp("S1 FAIL dW=[" as *u8); gn(dW[0]); gp("," as *u8); gn(dW[1]); gp("," as *u8); gn(dW[2]); gp("," as *u8); gn(dW[3]); gp("] want [24,28,40,44]\n" as *u8) } 31 32 // S2 dBias = 4 (OH*OW) 33 if dB[0]==nx_i32_to_f32(4) { pass=pass+1; gp("S2 stride-2 dBias=4 OK\n" as *u8) } 34 if dB[0]!=nx_i32_to_f32(4) { gp("S2 FAIL dB=" as *u8); gn(dB[0]); gp("\n" as *u8) } 35 36 // S3 dInput: with W=all-1 and dOut=all-1, each input cell that's covered gets +1. Stride 2 kernel 2 pad 0 on 4x4 37 // tiles EXACTLY (no overlap, no gap) -> EVERY input cell covered once -> dInput all = 1. 38 var allone: i64=1; i=0; while i<16 { if dinput[i]!=nx_i32_to_f32(1) { allone=0 } i=i+1 } 39 if allone==1 { pass=pass+1; gp("S3 stride-2 dInput all=1 (exact tiling) OK\n" as *u8) } 40 if allone==0 { gp("S3 FAIL dInput[0]=" as *u8); gn(dinput[0]); gp(" dinput[5]=" as *u8); gn(dinput[5]); gp("\n" as *u8) } 41 42 gp("CONV-BWD-STRIDE-GATE pass=" as *u8); gn(pass); gp("/3 rc=" as *u8); gn(rc); gp("\n" as *u8) 43 if pass==3 { gp("CONV-BWD-STRIDE-GATE verdict=GREEN 3/3 (strided backward is correct)\n" as *u8); sys_exit(0) } 44 sys_exit(1) 45 return 0 46}