non vorrei lavorare

昔はおもにプログラミングやガジェット系、今は?

Windows(MSVC)でmrubyからGPU対応のTensorflowを動かせた

こんにちは、長男が高熱をだし、時期が時期なので、インフルエンザを疑ったのですが、陰性で、その後もしばらく高熱がつづいたのですが、今では熱が下がり、大好きなYouTubeを見てます。@kjunichiです。

やったこと

タイトルの通りですが、以前このブログでも話題にしたmrubyかJuliaを呼び出せるmruby-juliaをWindowsのMSVC環境で動かせるようにして、 そこからJuliaからPythonを呼び出せるPyCallを経由して、すでにセットアップ済みのGPU対応のTensorflowを動かせました

JuliaをMSVC環境で動かそうとして分かったこと

.libファイルが必要

JuliaのWindows版はMinGWでビルドされているので、MSVCで動かすには.libファイルを作る必要がりました。

MSVCではCではJuliaを組み込めない

さらに、CからJuliaを呼び出すことは出来ず、C++からでないと、ダメでした。 そのため、mruby-juliaは元々Cオンリーであったのを、JuliaのAPIを叩く箇所をC++化して対応しました。 (mrubyでC++を使ったmrbgemを使うとちょっと問題があるのですが、これは別の記事で書く予定)

mrubyからTensorflowを呼び出す

事前準備

Juliaであらかじめ環境変数PYTHONGPUが有効なTensorflowが使えるPythonに設定した状態で、

Pkb.add("PyCall")

もしくは、

Pkb.build("PyCall")

しておく。

サンプルコード

j=Julia.new
j.eval("using PyCall")
j.eval("string(@pyimport tensorflow as tf)")
j.eval('sess = tf.Session()')
j.eval('a = tf.constant(10)')
j.eval('b = tf.constant(32)')
j.eval('sess[:run](pyeval("a + b", a=a, b=b))')
p j.eval('string(sess[:run](pyeval("a + b", a=a, b=b)))')

成果物

関連記事

12年前の記事

11年前の記事

2年前の記事

1年前の記事

Windowsでmruby-http2を動かした

こんにちは、kindle fireYouTubeで車モノ(knight riderやワイルドスピード)の映像を中毒患者の様に見まくる長男からタブレットを修理に出したといって、隔離してしばらくたち、今のところ、長男は隙を見て奥さんがおもに使っているChromebookYouTubeを見ています。@kjunichiです。

mruby-http2 for win32

Xeonで昨年末久々にPC組んだ流れで、Windowsでの開発環境をあれこれ試している。 そんな中、今回はmrubyでhttp2をしゃべることが可能になるmrbgemのmruby-http2をWindowsで動かしてみた。

事前に必要なモノ

  • openssl
  • libevent
  • nghttp2
  • zlib

zlib以外は、

- Windows 10でMSVCでnghttp2のサンプルを動かす

の記事に少し書いてます。

ヘッダ無い問題

以下に挙げるヘッダがWindowsでは用意されていない模様。

  • pwd.h
  • unistd.h
  • sys/socket.h
  • sys/wait.h
  • sys/resource.h
  • sys/queue.h
  • netdb.h
  • netinet/in.h
  • netinet/tcp.h
  • poll.h
  • signal.h
  • pthread.h
  • err.h

定数無い問題

mruby-http2をWindowsでビルドする際、以下の定数が未定義でエラーとなった。

  • F_GETFL
  • O_NONBLOCK
  • SHUT_WR

型や構造体無い問題

mruby-http2をWindowsでビルドする際、以下の型が未定義でエラーとなった。

  • ssize_t
  • uid_t
  • nfds_t
  • struct pollfd

関数無い問題

mruby-http2をWindowsでビルドする際、以下の関数が未定義でエラーとなった。

  • pipe
  • fcntl
  • alloca
  • gmtime_r
  • fork
  • TAILQ_FOREACH
  • kill
  • daemon

pipe

_pipeなる関数が用意されており、これを用いることで対応出来た。 ただし、引数がUNIXのpipeと異なり3つ必要。

#ifndef _WIN32
  rv = pipe(pipefd);
  #else
  rv = _pipe(pipefd, 65535, _O_BINARY);
#endif

作成するパイプのバッファサイズの指定は決め打ちで暫定的に対処した。

fcntl

mruby-http2ではfcntlでソケットをノンブロッキング指定にする為に用いられていた。 Windowsではこのような用途にはioctlsocketを用いることで対応出来た。

#ifndef _WIN32
  while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR)
    ;
  if (flags == -1) {
    mrb_raisef(mrb, E_RUNTIME_ERROR, "fcntl: %S", mrb_str_new_cstr(mrb, strerror(errno)));
  }
  while ((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR)
    ;
  if (rv == -1) {
    mrb_raisef(mrb, E_RUNTIME_ERROR, "fcntl: %S", mrb_str_new_cstr(mrb, strerror(errno)));
  }
  #else
  flags = 1;
  rv = ioctlsocket(fd, FIONBIO, &flags);
  if (rv != NO_ERROR) {
    mrb_raisef(mrb, E_RUNTIME_ERROR, "ioctlsocket: %S", mrb_str_new_cstr(mrb, "error")); // TODO
  }
#endif

シグナルがWindowsでないと勘違いしてた問題

シグナル周りは一旦全部コメントアウトして無視することにして対応した。

  • struct sigaction
  • sigaction

関数自体を無効にしたものたち

単純にWindowsで動かすにには不要な機能はスパッと諦めて作業した。 その結果、以下の関数は、戻るだけだったり、固定値を返すだけにしたり、関数そのものをコメントアウトした。

  • mrb_http2_get_uid
  • mrb_http2_config_get_worker
  • tune_rlimit

成果物

mrubyのbuild_config.rbに以下を記述することでwindowsでビルド可能なmruby-http2が利用できるハズ。

conf.gem :github => 'kjunichi/mruby-http2', :branch => 'support-for-win32'

まとめ

クライアントは、これらの問題を解決することで、動かせた。 サーバー側は、さらに対応が必要だった。これはまた、別の記事にするつもり。

ちなみに、mruby-cliでバイナリを作る場合は、今回のMSVCの対応とは別にmingw-w64での対応が必要となる。 もし、dockerを使わず直接Windows上でmruby-cliでワンバイナリをMSVCで作製すれば、今回のmrbgemが使えるかもしれません。

関連記事

11年前の記事

10年前の記事

9年前の記事

8年前の記事

7年前の記事

6年前の記事

5年前の記事

Rust入門者向けハンズオン #2 に行ってきた

おはようございます。昨年末あたりから、次男も箸でご飯を食べると言い出し、エジソンの箸で次男も食事をしています。@kjunichiです。

#

Rust入門者向けハンズオン #2 - connpass

let num = num + 1;

では、numが加算されなかった。

関連記事

13年前の記事

9年前の記事

8年前の記事

5年前の記事

4年前の記事