Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2008-08-15

CLでマルチスレッド (2)

| 01:25 | CLでマルチスレッド (2) - わだばLisperになる を含むブックマーク はてなブックマーク - CLでマルチスレッド (2) - わだばLisperになる

今回のお題は、一つのデータを複数のスレッドで分割して処理して効率化を狙うというもの。

(defpackage :ppb-data-split
  (:use :cl :portable-threads))

(in-package :ppb-data-split)

(defparameter *data* #(0 1 2 3 4 5 6 7 8 9))

(defun thread-func (name data)
  (declare (array data))
  (map nil (lambda (x)
             (format t "~A:~A + 1 = ~A~%" name x (1+ x)))
       data))

;; 実行
(do ((ths (list (spawn-thread "thread0" (lambda () (thread-func "thread0" (subseq *data* 0 4))))
                (spawn-thread "thread1" (lambda () (thread-func "thread1" (subseq *data* 4)))))))
    ((notany #'thread-alive-p ths) 'done))

;thread0:0 + 1 = 1
;thread0:1 + 1 = 2
;thread0:2 + 1 = 3
;thread0:3 + 1 = 4
;thread1:4 + 1 = 5
;thread1:5 + 1 = 6
;thread1:6 + 1 = 7
;thread1:7 + 1 = 8
;thread1:8 + 1 = 9
;thread1:9 + 1 = 10
;=> DONE

ベクタを半分に分割してスレッドに与えてみています。

ちなみに、自分はLISP系以外の言語が、からきし読めないので元コードが一体どんな感じなのか分かっておらず、元のコードを翻訳したものでは全くありません…。

前回もスレッドの終了をループを回して待機しているわけなのですが、一体これで良いのだろうか?無駄にCPUを使ってるんじゃないか?という疑問がわいてきました。待機のための専用の関数とかありそうな気が…。

とりあえず、先にcl-cookbookのスレッドの項目を実習して方が良いのかもという気も。

2008-08-14

CLでマルチスレッド (1)

| 01:55 | CLでマルチスレッド (1) - わだばLisperになる を含むブックマーク はてなブックマーク - CLでマルチスレッド (1) - わだばLisperになる

図書館でなんとなく「マルチコアCPUのための並列プログラミング—並列処理&マルチスレッド入門」という本を借りてきたのでなんとなくCLで例題を試して行ってみることにしました。

ANSI CLでは、スレッドについて規格が定まってはいないので、処理系依存となりますが、Allegro等のMPパッケージ等なんとなくそれなりに有名なものがあるようです。

これといった決め手もあるようなないような感じですが、処理系の差異を吸収しようという、Bordeaux Threadsや、Portable Threads等のパッケージがあるので、自分は、こちらの方を使ってみることにしました。そのうちAllegro系も試してみたいと思っています。

最初のお題の内容は、とりあえずスレッドを2つ作成して走らせてみよう、というもの。

生成→子スレッドの終了まで待機 という流れです。

(defpackage :ppb-first-thread
  (:use :cl :portable-threads))

(in-package :ppb-first-thread)

(defun thread-func (num lim)
  (dotimes (i lim)
    (format t "thread~A: ~A + 1 = ~A~%" num i (1+ i))
    (sleep (random 2))))

(do ((ths (list (spawn-thread "thread0" (lambda () (thread-func 0 10)))
                (spawn-thread "thread1" (lambda () (thread-func 1 10))))))
    ((notany #'thread-alive-p ths) 'done))

; thread0: 0 + 1 = 1
; thread0: 1 + 1 = 2
; thread0: 2 + 1 = 3
; thread1: 0 + 1 = 1
; thread1: 1 + 1 = 2
; thread1: 2 + 1 = 3
; thread1: 3 + 1 = 4
; thread0: 3 + 1 = 4
; thread1: 4 + 1 = 5
; thread1: 5 + 1 = 6
; thread0: 4 + 1 = 5
; thread0: 5 + 1 = 6
; thread0: 6 + 1 = 7
; thread0: 7 + 1 = 8
; thread0: 8 + 1 = 9
; thread0: 9 + 1 = 10
; thread1: 6 + 1 = 7
; thread1: 7 + 1 = 8
; thread1: 8 + 1 = 9
; thread1: 9 + 1 = 10
;=> DONE

sleepは入れなくても良いのですが、結果がばらけないと見た目が面白くないのでなんとなく入れてみました(*'-')