Weitere ähnliche Inhalte Mehr von Kazuhiro Hishinuma (17) Kürzlich hochgeladen (11) すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~1. すべてを Racket に取り込もう!
∼Racket FFI と Package システムの使い方∼
菱沼 和弘 (@kazh98)
明治大学理工学部情報科学科 数理最適化研究室
URL: http://www.mo.cs.meiji.ac.jp/kaz/
K. Hishinuma
すべてを Racket に取り込もう!
1 / 35
3. Let’s Introduction
[複名/U] マスハラ (mathematical harassment)
U : 数学徒,
V ⊂ U : 精神的苦痛を感じている数学徒,
T : U → U, 数学的を用いた言動.
T がマスハラである.
⇐⇒ ∃x ∈ U : T x ∈ V.
def
※このスライドもマスハラかもしれない
K. Hishinuma
すべてを Racket に取り込もう!
3 / 35
10. Racket Foreign Interface
Racket FFI
C 言語向けのライブラリを Racket から叩ける機能。
base パッケージにより標準提供。
FFI 機能の利用
(require ffi/unsafe ffi/unsafe/define)
(require ffi/vector) ; 配列型を扱う場合
K. Hishinuma
すべてを Racket に取り込もう!
10 / 35
12. Racket Foreign Interface
BLAS の Racket インターフェイスを書いてみた
成果物は、Github:
https://github.com/kazh98/blas
で公開しています。
※ Lv1 呼び出しのみ完成
K. Hishinuma
すべてを Racket に取り込もう!
12 / 35
13. Racket Foreign Interface
ライブラリのロード
ライブラリのロードには、ffi-lib 関数を用いる。
ffi-lib 関数
(ffi-lib ライブラリ名 #:fail 失敗時手続き)
ライブラリ名 ロードするライブラリの名前 (e.g. libc)
失敗時手続き ロード失敗時に呼び出される thunk
戻り値 FFI オブジェクトを返す。
これを define-ffi-definer 構文で捕捉すると、
FFI 定義子が手に入る。
K. Hishinuma
すべてを Racket に取り込もう!
13 / 35
14. Racket Foreign Interface
例. ライブラリのロード
(define-ffi-definer define-cblas
(ffi-lib libcblas #:fail (lambda ()
(ffi-lib libgslcblas))))
ライブラリ名 libcblas,libgslcblas を順に探す。
以後、define-cblas 構文が、FFI 定義子となる。
K. Hishinuma
すべてを Racket に取り込もう!
14 / 35
15. Racket Foreign Interface
インターフェイス定義
FFI 定義子 define-cblas を使って、
ライブラリ関数へのインターフェイスを定義する。
C 言語のプロトタイプ宣言に相当。
define-cblas 構文
(define-cblas 名前 型)
名前 ライブラリからインターフェイスを張る関数名
型 ライブラリから張られる関数の型
(_fun 引数型 1 引数型 2 ... - 戻り値型)
K. Hishinuma
すべてを Racket に取り込もう!
15 / 35
16. Racket Foreign Interface
インターフェイス定義型
C 言語
int
unsigned int
double
size_t
intptr_t
void*
char*
Racket
_int
_uint
_double*
_size
_intptr
_pointer
_string
C 言語
int32_t*
int64_t*
double*
Racket
_s32vector
_s64vector
_f64vector
呼び出し時には、スカラ型は対応する Racket の値を、
配列型は対応する SRFI-4 のベクタを用いればよい。
K. Hishinuma
すべてを Racket に取り込もう!
16 / 35
17. Racket Foreign Interface
例. インターフェイス定義
言語プロトタイプ宣言 (cblas.h)
C
double cblas_dnrm2(const int N,
const double *X, const int incX);
↓
Racket インターフェイス定義
(define-cblas cblas_dnrm2
(_fun _int _f64vector _int - _double))
これで、cblas_dnrm2 が普通の関数同様に呼び出せる。
K. Hishinuma
すべてを Racket に取り込もう!
17 / 35
18. Racket Foreign Interface
FFI 完成
(require math/cblas ffi/vector)
(cblas_dnrm2 2 (f64vector 3.0 4.0) 1)
;= 5.0
K. Hishinuma
すべてを Racket に取り込もう!
18 / 35
22. Package Management
provide の宣言
provide 構文を用いて、
外部参照可能な関数を指定する。
今回の例
(provide
cblas_dswap cblas_dscal cblas_dcopy cblas_daxpy
cblas_ddot cblas_dnrm2 cblas_dasum cblas_idamax)
※ FFI インターフェイスは、Racket 上では単なる手続きなので、
それらと同様にしてよい。
K. Hishinuma
すべてを Racket に取り込もう!
22 / 35
29. Package Management
公式見解
Eli Barzilay: The Racket Foreign Interface
It’s unfortunate that this literal has the
same name as - from racket/contract,
but it’s a different binding.
unfortunate か、それなら仕方ない。
……では済まないでしょ!!!
K. Hishinuma
すべてを Racket に取り込もう!
29 / 35
31. Package Management
info.rkt
Package のルートに、info.rkt を配置する。
info.rkt
#lang setup/infotab
(define collection ’multi)
(define version
バージョン番号)
(define deps
’(依存関係))
バージョン番号 数字とピリオド区切りの文字列
依存関係 依存するパッケージ名を表す文字列のリスト
K. Hishinuma
すべてを Racket に取り込もう!
31 / 35
33. あとがき
BLAS Interface for Racket の使用例
閉球 C := {x ∈ Rn : ∥x − c∥ ≤ r} への距離射影
{
x + ∥c−x∥−r (c − x) (∥x − c∥ r)
∥c−x∥
PC (x) :=
.
x
(Otherwise)
(require math/blas)
(define (PROJ C R X)
(let ((T (make-vect (vect-length C))) (U 0.))
(COPY C T)
(AXPY -1 X T)
(set! U (NRM2 T))
(when ( U R)
(AXPY (/ (- U R) U) T X))
X))
K. Hishinuma
すべてを Racket に取り込もう!
33 / 35
34. あとがき
参考文献
[1] E. Barzilay: The Racket Foreign Interface.
URI: http://docs.racket-lang.org/foreign/
[2] J. McCarthy: Package Management in Racket.
URI: http://docs.racket-lang.org/pkg/
[3] K. Hishinuma: Racket(Scheme) による Krasnosel’skii-Mann
iterations の数値実験.
URI: http://www.mo.cs.meiji.ac.jp/kaz/km-iter
[4] K. Hishinuma: K. Hishinuma: BLAS Interface for Racket.
URI: http://www.mo.cs.meiji.ac.jp/kaz/blas
K. Hishinuma
すべてを Racket に取り込もう!
34 / 35