MEP 4: タプルのvectorization
- Created: 2022-09-12 10:41:25
r, g, bには同じ処理をする事が多いので、vectorizationが欲しい。 以下みたいなの。
let [r3, b3, g3] = [r2, b2, g2]/a2
パーサーの段階で展開されるシンタックスシュガーにしたい。 現状はテンソルのタプルの扱いなどはletの所で展開しているけれど、expressionの所で展開したい。 そうすれば同じ処理でvectorizationも扱えるはず。
vectorizationしたいもの
- 割り算
- 掛け算
- cast_f32等
最後を考えるに、関数一般をvectorizationしてしまっても良いかも?
既存のスクリプトをvectorizationしてみる。
モザイク
@bounds( (input.extent(0)-1)/MOSAIC_WIDTH+1, (input.extent(1)-1)/MOSAIC_WIDTH+1)
def avg |x, y|{
rsum(0:MOSAIC_WIDTH, 0:MOSAIC_WIDTH) |rx, ry|{
let [a, r, g, b] = clamped( MOSAIC_WIDTH*x+rx, MOSAIC_WIDTH*y+ry )
let [r2, g2, b2] = [r, g, b]*a
[a, r2, g2, b2]
}
}
def result |x2, y2| {
let [a2, r2, g2, b2] = avg( x2/MOSAIC_WIDTH, y2/MOSAIC_WIDTH )
let [r3, g3, b3] = [r2, g2, b2]/a2
ifel(a2==0,
0,
argb( a2/(MOSAIC_WIDTH*MOSAIC_WIDTH),
r3,
g3,
b3 ) )
}
悪くないが、インラインでそのまま書けないものかなぁ。 以下のように書きたいが、spreadしてくれないといけない。
うーん。関数呼び出しも同じ感じで書きたいよなぁ。
argb( a2/(MOSAIC_WIDTH*MOSAIC_WIDTH),
[r2, g2, b2]/a2)
やりたいのは、タプルに対して演算した結果を個々の要素に展開したい。
JavaScriptのspread演算子は同じ事をする。
[a, ...[r, g, b]*a]
argb( a2/(MOSAIC_WIDTH*MOSAIC_WIDTH), ...[r2, g2, b2]/a2)
kotlin, python, rubyはアスタリスク(Rubyではsplatオペレーターと言うらしい)
[a, *[r, g, b]*a]
argb( a2/(MOSAIC_WIDTH*MOSAIC_WIDTH), *[r2, g2, b2]/a2)
swiftやrustには無さそう。
個人的にはJSの方が好きだが、業界的にはsplatで統一されつつあるのかなぁ。
vectorizationと合わせる事を考えると...の方がいい気がするな。 とりあえず...とvectorizationを合わせる方針で行ってみよう。
- ...は関数の引数とタプルの生成時のみサポート
- vectorizationは
/,*と任意の関数(タプルを引数に取る関数が必要になったらそれは特別扱い) - どちらもパースの段階で処理するシンタックスシュガー
最後が本当に実現出来るかは以下で簡単に考えておこう。
追記: やはり関数の最後のplace holderの ... との区別が面倒だったので、 *にする。
vectorizationは、IRとしては展開したものを持つ。 つまり
は、
と展開する。 つまりタプルの正体が分からないようなケースではうまく処理出来ない。 関数の引数がタプル、みたいなものの時。 ただ、テンソルの場合、
は、以下のような感じに展開されて、
[ts(x,y)[0], ts(x,y)[1], ts(x,y)[2]]/a2
以後は通常の展開になる予定。すべてのタプルはこのように、展開を記述出来るとする(現状はこうなっていないが)。そもそもtensorのタプルのケースでのindexは現状使った事無いのでサポートしていない気がする(いつもdestructuring代入で十分なので)。 これは関数の引数などでもサポートする時には考える必要がありそう(ただ、スクリプトとしてはいつもdestructuring代入のみでも十分な気もしないでもない)
castなどの関数やsinなどは、全てかってに展開される。 つまり、以下は、
展開されてIR上では以下のようになる。
[cast_u64(r), cast_u64(g), cast_u64(b)]
spreadの仕様
- タプルの初期化と関数呼び出しのarg listのみで使える
*をexprの前に置く事でそれを展開したものが引数として解釈される