nodes_outputにアクセスするコードを並び立てて、switch文で添字を定数にしてしまえば、汎用的なシェーダーで遺伝的プログラミングができそう。
つまり以下のような擬似コードになる
fn nodes_output_access(i:u32, nodes_output:array<i32>) i32 {
switch(i) {
case 0 { return nodes_output[0]}
case 1 { return nodes_output[1]}
...
}
}
fn nodes_exec(node:Node, nodes_output:array<i32>) {
let i1=nodes_output_access(node.index1, nodes_output);
let i2=nodes_output_access(node.index2, nodes_output);
return node_function_exec(node.function, i1, i2)
}
fn main(){
nodes_output[0] = node_exec(nodes[0], nodes_output);
nodes_output[1] = node_exec(nodes[1], nodes_output);
...
}
個体を作るごとにコンパイルしなくて良いので、学習データ数が少なくても早くなるはず。
やってみたところ、条件分岐の数が2倍になると、コンパイル、というかcompute pipelineの作成にかかる時間が10倍になった。ばかやろうじゃん。
条件分岐の数が1000にもなると、もはや待っていられない時間がかかる。
力技で解決するなら、wgpuに踏み込み、compute pipelineの作成を高速化するように書き換え、pull requestを出すと良いのだろう。