狠狠撸

狠狠撸Share a Scribd company logo
Menohにおける
C++実装 / C API / C++API
okdshin
「Menoh」というライブラリを開発している
https://github.com/pfnet-research/menoh
C++で実装
深層学習(DNN)モデルの推論用ライブラリ
Menohでできること
C++で物体認識(VGG16)を動かす
Menohでできること
Rustで物体検出(YOLOv2)を動かす
https://github.com/Hakuyume/menoh-yolo
Menohの特徴
● Intel製のライブラリ「MKLDNN」による
CPUでの高速なDNNモデルの推論
● オープンなDNNモデル保存フォーマット
「ONNX」のサポート
● シンプルなC APIとそれを利用して作られ
た様々な言語バインディング
Menohの特徴
● Intel製のライブラリ「MKLDNN」による
CPUでの高速なDNNモデルの推論
● オープンなDNNモデル保存フォーマット
「ONNX」のサポート
● シンプルなC APIとそれを利用して作られ
た様々な言語バインディング
C API? C++じゃないの?
C++で動的ライブラリのABIを維持すること
はほぼ不可能
利用者側のコードとはコンパイラのバージョンや設定までふくめて
全く同じ環境でコンパイルする必要がある
なので,ビルド済みの動的ライブラリを配布して使ってもらうことは
できない
また,コードを更新すると原則的にABIが崩れるので
毎回アップデートのたびにコードを全てビルドし直す必要がある
ABI(Aplication Binary Interface)
● API(Application Programming
Interface)のバイナリバージョン
● ライブラリやオブジェクトコードのABIが
合ってないとリンクに失敗する
Cで書くしかない!!
注意:C言語の標準でもABIが定まっているわけではない
定まっているわけではないが,特定のプラットフォー
ム内ではコンパイラの種類が違ったりしてもほぼ互
換性がある
例:x86_64のWindowsのABI
x86_64のWindows用にビルドしたDLLは
x86_64のWindows用の異なるコンパイラで利用できるし,
ABIを崩さないようにコードを修正できる
でもC++で実装したい
2018年にCはキツイ
(ひとによる?)
どうする
C++で実装してCのAPIを用意する
CのAPI
● 組込み型とPODな構造体のみ
● 名前空間や例外機構はなし
● リソース確保/解放関数はセットで用意
● クラスは構造体で隠蔽してその構造体のポインタ
でやり取りする
● 複雑なデータ構造は逐次的に作成できるようにす
る
コード例(menoh.cppから抜粋)
check_error関数(独自に定義)で例外をすべて
キャッチしてエラーコードに変換し返り値にする
デストラクタが使えない&リソースの確保と解放は同一の
モジュールで行う必要があるため,リソース確保関数と解
放関数はセットで用意する
名前空間が使えないため接頭辞を付ける
コード例
menoh.hから抜粋
menoh.cppから抜粋
C APIでは構造体のポインタで扱う
クラスは構造体に隠蔽する
複雑なデータ構造は逐次的に作成できるようにする
「配列の配列」や辞書的なデータ構造をやり取りしたい場合は逐
次的に構築するためのBuilderを用意する
これくらいならkeyとvalueの構造体を定義して配列で渡すこと
もできるが,もっとデータ構造が複雑になると大変になってくる
内部実装を隠蔽することで拡張もやりやすい
Pseudo code例
C APIだけでなく,C++APIも欲しい
2018年にC APIはキツイ
リソースの解放関数を手動で呼び出すのつ
らすぎる
エラー処理がエラーコードなのもつらい
initializer_listとか使えるようにしたい
どうする
● std::stringはstd::string::c_str()でC文字列に
● std::vectorはstd::vector::data()で配列に
● スマートポインタ(std::unique_ptr,
std::shared_ptr)のデリータをカスタマイズして解
放関数が自動で呼び出されるようにする
● オブジェクトのポインタをクラスに隠蔽してオブ
ジェクトに関連する関数をメンバー関数から呼び
出せるようにする
コード例(menoh.hppから抜粋)
std::unique_ptrのデリータをカスタマイズ
std::stringからc_str()でC文字列に変換
エラーコードをチェックして例外に変換
構造体のポインタをクラスに隠蔽
例外処理がものすごいことに
menoh.hpp (C++API)
menoh.h (C API)
menoh.cpp (C++実装)
その他のC++実装コード
例外処理がものすごいことに
menoh.hpp (C++API)
menoh.cpp (C++実装)
その他のC++実装コード例外発生
menoh.h (C API)
例外処理がものすごいことに
menoh.hpp (C++API)
menoh.cpp (C++実装)
その他のC++実装コード
例外をキャッチして
エラーコードに変換
例外発生
menoh.h (C API)
例外処理がものすごいことに
menoh.hpp (C++API)
menoh.cpp (C++実装)
その他のC++実装コード
menoh.h (C API)
例外をキャッチして
エラーコードに変換
エラーコードを返り値として
ユーザーに渡す
例外発生
例外処理がものすごいことに
menoh.cpp (C++実装)
menoh.hpp (C++API)
その他のC++実装コード
返り値のエラーコードを
チェックして例外を投げる
menoh.h (C API)
例外発生
例外をキャッチして
エラーコードに変換
エラーコードを返り値として
ユーザーに渡す
それはそれとしてC APIを用意すると世界がひらける
Menohのたくさんの言語バインディング
C++バインディングのABIは大丈夫なのか
menoh.hppは実装がすべてヘッダに直書き
になっているのでユーザーはincludeするだ
けで使える
すなわち,常にユーザーコードと同じプラッ
トフォーム,コンパイラ,コンパイラオプショ
ンでビルドされる
ABIの互換性の問題は起こらない
まとめ
● C++のライブラリを書いたら,ぜひ他の言語からも利
用できるようにC APIも用意しよう
● C APIではC++の機能が使えないのでうまく変換しよ
う(例外はエラーコードに,クラスは構造体に隠蔽,
データ構造は逐次作成できるようにするなど)
● C APIを使ったC++APIも用意しよう
● C++APIではstd::stringとstd::vectorとスマートポイン
タを駆使してC APIを隠蔽しよう.その際,実装は全
部ヘッダーに書いてABI互換の問題を回避しよう
画像の出典
? C, C++, Ruby, C#, NodeJS, Java, Python logos are from icon8 (https://icons8.com/)
? “https://golang.org/doc/gopher/frontpage.png” by Renée French is licensed
under CC BY 3.0 (https://creativecommons.org/licenses/by/3.0/)
? “https://www.rust-lang.org/logos/rust-logo-128x128-blk.png” by Rust lang
organization is licensed under CC BY 4.0
(https://creativecommons.org/licenses/by/4.0/)
? Haskell, OCaml, Julia logos are public domain on Wikipedia.

More Related Content

MenohにおけるC++実装 / C API / C++API