読者です 読者をやめる 読者になる 読者になる

non vorrei lavorare

ブログ名の通りです。javascript three.js mruby rust OCaml golang julialang blender

mruby-uuid作った

こんばんは、次男が熱を出し、家にいます。kjunichiです。GLSLをサーバサイドで処理して、HLSで配信するWebアプリを作成している際に、必要と思いこみ作ってしまったmrbgemの話になります。

ユニークなファイル名をつけたかった

pt(the_platinum_searcher)でお世話になってる作者の方が作成されたmrbgemがあった。

github.com

/dev/urandomを使っての実装で、一瞬OSXでは使えないと思いったが、OSXにも/dev/urandomがあった。

が、勢いで、ossp-uuidを呼び出すmrbgemを作ってしまった。

github.com

比べてみた

% cat uuid1.rb
100000.times {
  SecureRandom.uuid
}

% time bin/mruby uuid1.rb 

real    0m32.059s
user    0m2.332s
sys     0m29.657s

$ cp uuid1.rb uuid2.rb                                                           
$ vi uuid2.rb 
$ cat uuid2.rb
100000.times {
  Uuid.uuid
}
$ time bin/mruby uuid2.rb                                                        

real    0m3.380s
user    0m0.547s
sys     0m2.814s

もしかした、用途によっては意味のあるmrbgemかも?

GPUを使って、mrubyでのaobenchを更に速くした

おはようございます。先週は、次男のトビヒがひどくなり、奥さんが皮膚科に連れて行き、 その指示に従い、自分が、毎日次男の患部に薬をつけ、包帯を巻いていました。 それが、長男にもうつった疑惑があり、週の後半は長男もプール見学させてました。 kjunichiです。

背景

aobenchの高速化にあたり、julialangでマルチプロセス化するも、パフォーマンス悪化、そこでmruby-aobench-nativeを作った。 折角なのでと、pthread使ってマルチスレッド化を試みるも、これまた、思うようなパフォーマンスが出なかった。 何とかしたい!

GPUのちからを借り、mruby-glslを作った。

f:id:kjw_junichi:20160809072340p:plain

mruby-glslとは

GLSLをmrubyのヒアドキュメントに書いて、これのレンダリング結果をバイナリ形式のppmデータとして 取得できるmrbgem。

そこそこの演算が必要になる画像データをGLSLによりGPUの高速な演算能力を利用して高速に取得可能となる。

ほんとに速いのか?

aobenchで比較

time bin/mruby benchmark/bm_ao_render.rb >ba.ppm

real    7m16.417s
user    7m10.905s
sys 0m2.536s

出力画像サイズを256x256に変更して実行。

  • 先日のmruby-aobench-native
  • OSX
time bin/mruby aon.rb > aon.ppm

real    0m2.991s
user    0m2.960s
sys 0m0.019s
  • 今回のmruby-glsl
  • OSX
time bin/mruby aoglsl.rb >aoglsl.ppm

real    0m1.011s
user    0m0.074s
sys 0m0.056s

CPU実行に比べて、速くなった。

mruby-glslを通して学べたこと

インスタンス変数の取得

rubyで定義したクラスの中のインスタンス変数にCからアクセスする。

mrb_intern_litでインスタンス変数名をmrubyのシンボル型に変換して、 これをmrb_iv_getに指定することで、インスタンス変数が取得出来た。

mrb_value shader;
shader = mrb_iv_get(mrb, obj, mrb_intern_lit(mrb, "@vertexShader"));

Cの文字列とmrubyの文字列の相互変換

mrubyからC

int len;
const char *source;

len = RSTRING_LEN(shader);
source = RSTRING_PTR(shader);

Cからmruby

int size;
const char *buf="hogefuga";
mrb_value mrbStr;

mrbStr = mrb_str_new(mrb, buf, stelen(buf));

snprintfの返り値がヤバい

書き込んだバイト数ではなく、書き込んだとしたら 何バイト使うかを返す。

ググって出てきたIBMサンプルが、paiza.ioで動かず、調査してわかった。 どうも、昔のsnprintfとC99あたりで規格ができてからのsnprintfは 挙動が違うものがあるのかも?

glReadPixelsでOpenGLの描画内容の取得

遅いと評判のglReadPixelsは大昔に使ったことがあるハズなので、 一旦これで実装してみた。

WindowsでMSVC++環境下での外部ライブラリを参照するmrbgemsの作りか

OSX以外でも試したく、Windowsにも対応してみた。

今回はWindows環境で、glfw3+Openglな描画環境でうごくコードが扱えた。

に成果が詰まってる。

OpenGLの新しめのバージョンをglfwで利用するには

まだ、これはmrbgemには取り込んでいないが、

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

特に

glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

が重要、これがないとOpenGLの初期化で失敗した。

mrubyでaobenchを動かし、GIFアニメを出力できるようにした

パソコン・インターネット

こんばんは、奥さんが出張のため、またまた実家に来ています。3歳ともうすぐ5歳になる息子たちも一時期に比べ、電車での世田谷の自宅から、中野の実家までの移動も楽になってきたことを実感してます。kjunichiです。

mrubyでaobenchを動かし、動画にする

静止画はつまらないので、高速化して、GIFアニメを出力できるようにした。

f:id:kjw_junichi:20160723175205g:plain

成果物

build_config.rb

conf.gem :github => 'kjunichi/mruby-aobench-native'
conf.gem :github => 'kjunichi/mruby-mrmagick'

aoanim.rb

s0 = {:x => -2.0, :y => 0.0, :z => -3.5}
s1 = {:x => -0.5, :y => 0.0, :z => -3.0}
s2 = {:x => 1.0, :y => 0.0, :z => -2.2}

gif = Mrmagick::ImageList.new

for i in 1..50
  Ao.init_scene(s0, s1, s2)
  img = Mrmagick::ImageList.new
  img.from_blob(Ao.render)
  gif.push img
  s0[:x] = s0[:x] + 0.1
  s1[:x] = s1[:x] - 0.03
  s1[:z] = s1[:z] + 0.08
  s2[:x] = s2[:x] + 0.05
end

gif.write("ao.gif")

aobenchのネイティブ化の成果

bm_ao_render.rbは256x256の出力サイズに変更済み。

$ time build/bench/bin/mruby benchmark/bm_ao_render.rb >aorender.ppm

real    2m51.207s
user    2m48.690s
sys 0m1.311s

$ time bin/mruby ao.rb 
fname = ao.ppm

real    0m1.555s
user    0m1.510s
sys 0m0.015s

まとめ

mruby-juliaを作ったので、aobenchをJuliaで動かし、 これをmruby-juliaから使うことで、mrubyのaobenchを 速くしたという記事を書きたかったが、現状の自分のjulia力だと aobenchが速くならず、それならばということで、Cのオリジナル 実装をちょっと変更して、mruby側にオンメモリーppmを出力 して、mruby-mrmagickをオンメモリーのデータを扱えるようにすることで、 このデータをGIFファイル化が可能となった。

関連記事