Upgrade to Pro — share decks privately, control downloads, hide ads and more …

名古屋Ruby会議05_LT.pdf

Avatar for Yuji Teshima Yuji Teshima
September 18, 2026
61

 名古屋Ruby会議05_LT.pdf

Avatar for Yuji Teshima

Yuji Teshima

September 18, 2026

Transcript

  1. Ruby のブロックが、 GPU のカーネルになる mruby で GPU 計算をする話 ─ 株式会社スタジアム(懇親会スポンサー)

    名古屋Ruby会議05 二〇二六年九月十九日 大須演芸場 mruby 4.0.0 / Vulkan Compute / Raspberry Pi 5・Apple M5 名古屋Ruby会議05 開口一番 二席目
  2. Ruby で書けば、一行 mruby-gpu-narray a = GPU::SFloat.new(1024).seq b = a *

    2 + 1 b.to_a 見た目は普通の配列、中身は GPU 名古屋Ruby会議05 開口一番 二席目
  3. mruby-gpu-kernel の使い方 gem を一つ足す。本体の mruby-gpu-narray は自動で付いてくる conf.gem mruby-gpu-kernel # ビルド設定に、この一行

    a.map { |x| x * 2 + sin(x) } # 普段は、これだけ k = GPU.kernel { |x| x * 2 + sin(x) } # シェーダを作って、取って おく k.call(a) # 何度でも走らせる GPU.kernel_source { |x| x * 2 + sin(x) } # 中身(GLSL)を覗く 名古屋Ruby会議05 開口一番 二席目
  4. ブロックが、シェーダになる a.map { |x| x * 2 + sin(x) }

    ブロックを一回だけ動かして、 書記が帳面に写す。 帳面を GPU の言葉に翻訳して、渡す。 往復は、一度きり。 名古屋Ruby会議05 開口一番 二席目 layout(local_size_x = 256) in; layout(set = 0, binding = 0) buffer BufA { float a[]; }; layout(set = 0, binding = 1) buffer BufB { float b[]; }; layout(push_constant) uniform PushConstants { uint n; } pc; // generated by GPU.kernel void main() { uint idx = gl_GlobalInvocationID.x; if (idx >= pc.n) { return; } float x = a[idx]; b[idx] = ((x * 2.0) + sin(x)); }
  5. GPU の本職は、絵 配列の番号から、座標が出る x = mod(i, 256) # 番号 ÷

    256 の余り → 横 y = floor(i / 256) # 番号 ÷ 256 の商 i.map { |i| ... } # この座標なら、この明るさ 名古屋Ruby会議05 開口一番 二席目 → 縦
  6. map の中身 四枚ぶんを計算してから、座標で一枚を選ぶ i.map { |i| x = mod(i, 360.0);

    y = floor(i / 360.0) tx = floor(x / 180.0); ty = floor(y / 180.0) lx = x - tx * 180.0; ly = y - ty * 180.0 # どのタイルか(0 か 1) # タイルの中の座標 sea = 青海波(半径 24 の円を 4 段、Ruby のループで重ねる) crest = 丸に三つ引き(輪と、横棒 3 本) ichi = mod(floor(lx / 30.0) + floor(ly / 30.0), 2.0) * 200.0 + 30.0 heart = (x² + y² − 1)³ − x²y³ < 0 の内側 top = mix(sea, crest, step(0.5, tx)) bottom = mix(ichi, heart, step(0.5, tx)) mix(top, bottom, step(0.5, ty)) } 名古屋Ruby会議05 開口一番 二席目 # 上段: 左か右か # 下段 # 上段か下段か
  7. 出てきたシェーダは、一行 ブロック一つから、改行なしの 8,500 文字 b[idx] = mix(mix(mix(mix(mix(mix(((mod(x, 360.0) - (floor((mod(x,

    360.0) / 180.0)) * 180.0)) * 0.0), ((step(0.5, fract((sqrt((pow(((mod(x, 360.0) - (floor((mod(x, 360.0) / 180.0)) * 180.0)) - ((floor(((((mod(x, 360.0) - (floor((mod(x, 360.0) / 180.0)) * 180.0)) (mod((floor(((floor((x / 360.0)) - (floor((floor((x / 360.0)) / 180.0)) * 180.0)) / 12.0)) + -1.0), 2.0) * 24.0)) / 48.0) + 0.5)) * 48.0) + (mod((floor(((floor((x / 360.0)) (floor((floor((x / 360.0)) / 180.0)) * 180.0)) / 12.0)) + -1.0), 2.0) * 24.0))), 2.0) + pow(((floor((x / 360.0)) - (floor … 名古屋Ruby会議05 開口一番 二席目