35
すべてを Racket に取り込もう! Racket FFI Package システムの使い方~ 菱沼 和弘 (@kazh98) 明治大学理工学部情報科学科 数理最適化研究室 URL: http://www.mo.cs.meiji.ac.jp/kaz/ K. Hishinuma すべてを Racket に取り込もう! 1 / 35

すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Embed Size (px)

DESCRIPTION

すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~ Lisp Meet Up presented by Shibuya.lisp #14 発表資料

Citation preview

Page 1: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

すべてをRacketに取り込もう!~Racket FFIと Packageシステムの使い方~

菱沼 和弘 (@kazh98)

明治大学理工学部情報科学科 数理最適化研究室URL: http://www.mo.cs.meiji.ac.jp/kaz/

K. Hishinuma すべてを Racket に取り込もう! 1 / 35

Page 2: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Let’s Introduction

数学徒の苦悩

マスハラという言葉をご存知ですか?

K. Hishinuma すべてを Racket に取り込もう! 2 / 35

Page 3: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Let’s Introduction

[複名/U] マスハラ (mathematical harassment)

U :数学徒,

V ⊂ U :精神的苦痛を感じている数学徒,

T : U → U,数学的を用いた言動.

T がマスハラである.

⇐⇒def

∃x ∈ U : Tx ∈ V.

※このスライドもマスハラかもしれない

K. Hishinuma すべてを Racket に取り込もう! 3 / 35

Page 4: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Let’s Introduction

例. 水面上のマスハラ

「ちょっとそれ証明してよ」「本当にそれ定義から言えるの?」「・・・(板書への無言の視線)」

K. Hishinuma すべてを Racket に取り込もう! 4 / 35

Page 5: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Let’s Introduction

しかし!

CS系数学徒には、知られざる水面下のマスハラもあるのです!!!

K. Hishinuma すべてを Racket に取り込もう! 5 / 35

Page 6: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Let’s Introduction

例. 水面下のマスハラ

「数値計算ならFORTRAN使わなきゃ」「FORTRANに良いライブラリがあるよ~」README: Available for Fortran77

K. Hishinuma すべてを Racket に取り込もう! 6 / 35

Page 7: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Let’s Introduction

FORTRAN地獄

いつまでそんな太古の言語を使っているんだ!!

K. Hishinuma すべてを Racket に取り込もう! 7 / 35

Page 8: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Let’s Introduction

備考

Fortran (1957–)

Lisp (1958–)

……やばい、そんなに違いない

K. Hishinuma すべてを Racket に取り込もう! 8 / 35

Page 9: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Let’s Introduction

ということで、

///////////////過去の遺産人類の叡智を、1年未来の言語から呼びだそう!!

Lispで書くことに幸せを感じる人間もいるのです

K. Hishinuma すべてを Racket に取り込もう! 9 / 35

Page 10: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Racket Foreign Interface

Racket FFI

C言語向けのライブラリをRacketから叩ける機能。baseパッケージにより標準提供。

FFI機能の利用� �(require ffi/unsafe ffi/unsafe/define)

(require ffi/vector) ; 配列型を扱う場合� �

K. Hishinuma すべてを Racket に取り込もう! 10 / 35

Page 11: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Racket Foreign Interface

ということは?

FORTRANライブラリ→Cインターフェイス

→Racket FFI

で、Racketから呼び出せる!!!

K. Hishinuma すべてを Racket に取り込もう! 11 / 35

Page 12: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Racket Foreign Interface

BLASのRacketインターフェイスを書いてみた

成果物は、Github:

https://github.com/kazh98/blas

で公開しています。

※Lv1呼び出しのみ完成

K. Hishinuma すべてを Racket に取り込もう! 12 / 35

Page 13: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Racket Foreign Interface

ライブラリのロード

ライブラリのロードには、ffi-lib関数を用いる。ffi-lib関数� �(ffi-lib "ライブラリ名" #:fail 失敗時手続き)

ライブラリ名 ロードするライブラリの名前 (e.g. libc)

失敗時手続き ロード失敗時に呼び出される thunk

戻り値 FFIオブジェクトを返す。これを define-ffi-definer構文で捕捉すると、FFI定義子が手に入る。� �

K. Hishinuma すべてを Racket に取り込もう! 13 / 35

Page 14: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

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

Page 15: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Racket Foreign Interface

インターフェイス定義

FFI定義子 define-cblasを使って、ライブラリ関数へのインターフェイスを定義する。C言語のプロトタイプ宣言に相当。

define-cblas構文� �(define-cblas 名前 型)

名前 ライブラリからインターフェイスを張る関数名型 ライブラリから張られる関数の型

(_fun 引数型 1 引数型 2 ... -> 戻り値型)� �K. Hishinuma すべてを Racket に取り込もう! 15 / 35

Page 16: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Racket Foreign Interface

インターフェイス定義型

C言語 Racketint _int

unsigned int _uint

double _double*

size_t _size

intptr_t _intptr

void* _pointer

char* _string

C言語 Racketint32_t* _s32vector

int64_t* _s64vector

double* _f64vector

呼び出し時には、スカラ型は対応する Racketの値を、配列型は対応する SRFI-4のベクタを用いればよい。

K. Hishinuma すべてを Racket に取り込もう! 16 / 35

Page 17: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Racket Foreign Interface

例. インターフェイス定義

C言語プロトタイプ宣言 (cblas.h)� �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

Page 18: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

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

Page 19: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Package Management

再利用可能のために

Racket新機能のPackageシステムで、標準に準拠した 1ライブラリを書こう!

1http://pkgs.racket-lang.org/で公開できるK. Hishinuma すべてを Racket に取り込もう! 19 / 35

Page 20: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Package Management

ライブラリ作成の手順

1 ファイルの配置とprovide2 info.rktの作成3 Githubで公開

K. Hishinuma すべてを Racket に取り込もう! 20 / 35

Page 21: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Package Management

ファイルの配置

(require [パッケージ名]/[ライブラリ名])

で読み込まれるライブラリを、/[パッケージ名]/[ライブラリ名].rkt

に配置する。今回の例� �/math/blas.rkt

/math/cblas.rkt� �K. Hishinuma すべてを Racket に取り込もう! 21 / 35

Page 22: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

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

Page 23: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Package Management

みなさま

お気づきでしょうか・・・悲劇に向かって直進してきたことを。

K. Hishinuma すべてを Racket に取り込もう! 23 / 35

Page 24: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Package Management

なんということをしてくれたのでしょう

K. Hishinuma すべてを Racket に取り込もう! 24 / 35

Page 25: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Package Management

なんということをしてくれたのでしょう!

K. Hishinuma すべてを Racket に取り込もう! 25 / 35

Page 26: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Package Management

なんということをしてくれたのでしょう!!

K. Hishinuma すべてを Racket に取り込もう! 26 / 35

Page 27: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Package Management

契約プログラミングへの冒涜

FFIが、関数契約生成子->と同じ名前->を使うので、契約付きprovideなど2

ができない!!

2see, http://www.mo.cs.meiji.ac.jp/kaz/km-iterK. Hishinuma すべてを Racket に取り込もう! 27 / 35

Page 28: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Package Management

エラーになる例

(provide

cblas_dswap cblas_dscal cblas_dcopy

(contract-out

(SWAP (-> f64vector? f64vector? void?))

(SCAL (-> real? f64vector? void?))

(COPY (-> f64vector? f64vector? void?))))

K. Hishinuma すべてを Racket に取り込もう! 28 / 35

Page 29: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

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

Page 30: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Package Management

対策

FFIインターフェイス定義のみを、別ファイルに隔離する。blas.rkt (requireされる)ライブラリcblas.rkt FFI定義の隔離先

K. Hishinuma すべてを Racket に取り込もう! 30 / 35

Page 31: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Package Management

info.rkt

Packageのルートに、info.rktを配置する。info.rkt� �#lang setup/infotab

(define collection ’multi)

(define version "バージョン番号")

(define deps ’(依存関係))

バージョン番号 数字とピリオド区切りの文字列依存関係 依存するパッケージ名を表す文字列のリスト� �

K. Hishinuma すべてを Racket に取り込もう! 31 / 35

Page 32: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

Package Management

Githubで公開

あとは、作ったものをGithubで公開すればOK!

% raco pkg install github://github.com/

ユーザ名/リポジトリ名/master

とか叩けば、ライブラリをインストールできる。

K. Hishinuma すべてを Racket に取り込もう! 32 / 35

Page 33: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

あとがき

BLAS Interface for Racket の使用例閉球C := {x ∈ Rn : ∥x− c∥ ≤ r}への距離射影

PC(x) :=

{x+ ∥c−x∥−r

∥c−x∥ (c− x) (∥x− c∥ > r)

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

Page 34: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

あとがき

参考文献

[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-Manniterationsの数値実験.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

Page 35: すべてをRacketに取り込もう! ~Racket FFI と Package システムの使い方~

あとがき

Thanks for your listening.

K. Hishinuma すべてを Racket に取り込もう! 35 / 35