1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

並列Lispで、たらいまわしをした話

Last updated at Posted at 2023-07-16

動機

ISLispの生みの親の一人である伊藤貴康先生の論文を読みました。並列マシンの製作、その上で走るPaiLispに興味を持ちました。その論文を参考にしてISLisp規格のEasy-ISLisp(以下「EISL」)に並列構文、pletとpcallを追加、並列Lispで何ができるのだろうか?と試行錯誤しています。

スレッドセーフ

インタプリタをスレッドセーフにするとともに、コンパイラが生成するLispオブジェクトもスレッドセーフにしました。EISLはLispコードをC言語にトランスパイルする方式です。スレッド番号を表す引数thを追加するようにしました。

int f_tarai(int x, int y, int z, int th){
    tarai(x,y,z,th)
}


int tarai(int x, int y, int z, int th){
    コード本体
}

C言語の引数はスレッドセーフですが、動的変数、シンボルや文字列を表すセルはスレッド間で共有していますので、これをスレッド番号ごとに管理するコードを生成するように変更しました。マーク&スイープのGCスレッドごとに保護すべきセルなどのデータを保持し、スレッドセーフを実現しました。

C言語のPthreadライブラリを利用してスレッドに分割します。これによりマルチコアCPUであればそのスレッドが各コアで実行されるようになります。

並列構文

PaiLispの論文を参考にして次のように記述することとしました。

(defun ptarai (x y z)
    (the <fixnum> x)(the <fixnum> y)(the <fixnum> z)
    (if (<= x y)
        y
        (pcall ptarai (tarai (- x 1) y z)
                      (tarai (- y 1) z x)
                      (tarai (- z 1) x y))))

(defun pcount (n)
    (plet ((a (count 1 (div n 2)))
           (b (count (+ (div n 2) 1) n)))
     t))

(defun count (m n)
    (if (= m n)
        t
        (count (+ m 1) n)))

pcallは (pcall fn arg1 arg2 ...argn) という形式です。arg1,...argnをスレッドで起動、マルチコアで実行します。

pletはlet構文のマルチスレッド版です。式の部分をスレッドに分解して実行し、これをjoinで待機したのちにbody部を実行します。

余談ですが、EISLは型推論器をもっており、the構文により必要な情報を与えると最適化するようにしてあります。たらい回しのような単純な再帰コードの場合、C言語波の実行速度を出すことができます。

計測

インテルicore5で計測しました。Windows WSLで実行しています。

bandicam 2023-07-16 18-24-45-538.jpg

予想に反して並列のpfibの方が逐次のfibより若干遅いのでした。pthreadの設定の問題だろうか?などChatGPTに相手になってもらいかなり試行錯誤したのですが、残念ながら並列の方が遅くなっています。ARMラズパイ400では並列の方が高速になっています。たらい回し、竹内関数の場合にはその再帰パターンは複雑なのでなかなか並列での性能が上げられないでいます。スレッドに分割するコストを考えても2倍くらいは高速になると予想していたのですが。ちょっとがっかり。

CPUによる違い

英語版Reddit/Lispには凄腕Lisperがた出入りしているように思いました。記事を投稿し、いくつか助言をいただきまいした。改良の余地はあるかもしれません。また、コンカレントGCと並列動作とかまだ共存できずにセグフォを起こしています。並列動作を理解しつつじっくりデバグしています。

インテル、AMD、ARM それぞれ設計方針が異なるようで並列動作したときのパフォーマンスが異なります。ARMの方が並列で効果を出せています。インテルicoreは単一スレッドの高速性を重視しているのかもしれません。

EISLはGithubにおいてります。よかったらお試しください。
https://github.com/sasagawa888/eisl

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?