LoginSignup
4
1

More than 5 years have passed since last update.

emscripten で SIMD.js を使う

Last updated at Posted at 2017-03-16

emscripten で SIMD.js を使う

コンパイル時とリンク時に emcc -s SIMD する

SIMD.js が使われるケースは3種類ある。

  1. clang デフォルトの LLVM autovectorization が働いて自動的に SIMD 化する
  2. GCC 拡張の SIMD Vector Extensions で明示的に使う
  3. x86 の Streaming SIMD Extensions 命令を使う。詳細は 大本営 を読むべし

opencv など sse サポートしているものをを asm.js にする場合は 3 が使えそう

SIMD.js が有効なブラウザを用意する

-s SIMD で JS 出力すると SIMD.js の polyfill が付いてくる。
これをそのまま使うと遅くなる。

2017年上半期現在標準で SIMD が有効なブラウザはない

chrome の場合起動フラグでV8の起動フラグを渡せば有効になる。

chrome --js-flags="--harmony-simd"

使える V8 起動フラグの一覧を見るには chrome --js-flags="--help"

フラグ指定して起動する方法はリンク参照

ビルド例(opencv の場合)

1. configure

-s SIMD=1 をつけて cmake する

git clone https://github.com/opencv/opencv.git
cd opencv
mkdir build
cd build
OPTS='-O2 --llvm-lto 1 -s SIMD=1'
emcmake cmake \
  -DCMAKE_BUILD_TYPE=RELEASE \
  -DBUILD_DOCS=OFF \
  -DBUILD_EXAMPLES=OFF \
  -DBUILD_PACKAGE=OFF \
  -DBUILD_WITH_DEBUG_INFO=OFF \
  -DBUILD_opencv_cuda=OFF \
  -DBUILD_opencv_cudaarithm=OFF \
  -DBUILD_opencv_cudabgsegm=OFF \
  -DBUILD_opencv_cudacodec=OFF \
  -DBUILD_opencv_cudafeatures2d=OFF \
  -DBUILD_opencv_cudafilters=OFF \
  -DBUILD_opencv_cudaimgproc=OFF \
  -DBUILD_opencv_cudaoptflow=OFF \
  -DBUILD_opencv_cudastereo=OFF \
  -DBUILD_opencv_cudawarping=OFF \
  -DENABLE_PRECOMPILED_HEADERS=OFF \
  -DWITH_1394=OFF \
  -DWITH_CUDA=OFF \
  -DWITH_CUFFT=OFF \
  -DWITH_EIGEN=OFF \
  -DWITH_FFMPEG=OFF \
  -DWITH_GIGEAPI=OFF \
  -DWITH_GSTREAMER=OFF \
  -DWITH_GTK=OFF \
  -DWITH_JASPER=OFF \
  -DWITH_JPEG=OFF \
  -DWITH_OPENCL=OFF \
  -DWITH_OPENCLAMDBLAS=OFF \
  -DWITH_OPENCLAMDFFT=OFF \
  -DWITH_OPENEXR=OFF \
  -DWITH_PNG=OFF \
  -DWITH_PVAPI=OFF \
  -DWITH_TIFF=OFF \
  -DWITH_LIBV4L=OFF \
  -DWITH_WEBP=OFF \
  -DWITH_PTHREADS_PF=OFF \
  -DBUILD_opencv_apps=OFF \
  -DBUILD_PERF_TESTS=OFF \
  -DBUILD_TESTS=OFF \
  -DBUILD_SHARED_LIBS=OFF \
  -DENABLE_SSE=OFF \
  -DENABLE_SSE2=OFF \
  -DENABLE_SSE3=ON \
  -DENABLE_SSE41=OFF \
  -DENABLE_SSE42=OFF \
  -DENABLE_AVX=OFF \
  -DENABLE_AVX2=OFF \
  -DCMAKE_CXX_FLAGS=$OPTS \
  -DCMAKE_EXE_LINKER_FLAGS=$OPTS \
  -DCMAKE_CXX_FLAGS_DEBUG=$OPTS \
  -DCMAKE_CXX_FLAGS_RELWITHDEBINFO=$OPTS \
  -DCMAKE_C_FLAGS_RELWITHDEBINFO=$OPTS \
  -DCMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO=$OPTS \
  -DCMAKE_MODULE_LINKER_FLAGS_RELEASE=$OPTS \
  -DCMAKE_MODULE_LINKER_FLAGS_DEBUG=$OPTS \
  -DCMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO=$OPTS \
  -DCMAKE_SHARED_LINKER_FLAGS_RELEASE=$OPTS \
  -DCMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO=$OPTS \
  -DCMAKE_SHARED_LINKER_FLAGS_DEBUG=$OPTS \
  ../

-DENABLE_SSE3=ON にする

2. make

emmake make -j 4

これで llvm bitcode な libopencv_*.a ができる

3. リンク

あらかじめ用意しておいた opencv を使用するプログラム my_program.bc とリンクする

emcc \
  ./my_program.bc \
  ./lib/libopencv_video.a \
  ./lib/libopencv_imgproc.a \
  ./lib/libopencv_core.a \
  ./3rdparty/lib/libzlib.a \
  -O2 --llvm-lto 1 -s SIMD=1 \
  -o ./my_program.bc

llvm-nm my_program.bc でシンボルが見える

基礎的な注意点として 依存するライブラリは順番を後ろにすること。
例えば libopencv_imgproc.a は libzlib.a に依存し、
libopencv_video.a は libopencv_core.a に依存している。

4. asm.js へコンパイル

emcc \
  my_program.bc \
  -O2 --llvm-lto 3 -s SIMD=1 \
  -s TOTAL_MEMORY=33554432 \
  -s ASSERTIONS=0 \
  -o ./cv.js

これで SIMD が有効なブラウザだと例えば cv::calcOpticalFlowFarneback が 4 倍ほど速くなる

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1