1

私はSBCLを使用して研究プロジェクトのスクリプトをコーディングしていましたが、SB-TREAHDを試したのはこれが初めてです。各スレッドは、sb-ext:run-programが使用される外部シェルコマンドを数回呼び出します。

問題は、ext:run-programが提示されるたびに、プログラムがデッドロックに陥る可能性があることです(mutexのようなものを明示的に使用しなかった場合)。しばらく実験しましたが、解決策が見つかりませんでした。デッドロックを発生させる可能性のあるコードの簡略化されたバージョンは次のとおりです。

(use-package :sb-thread)

;;; Global Settings
(defparameter *path-num* 4)
(defparameter *testing* nil)
(defparameter *training* nil)
(defparameter *shared-folder* "shared")
(defparameter *template* "template.conf")
(defparameter *pwd* (namestring (truename ".")))


;;; Utilities
(defmacro compose-file-name (&rest parts)
  "compose a filename under current *pwd*"
  `(concatenate 'string *pwd* 
        ,@(mapcar (lambda (x) `(format nil "/~a" ,x))
              parts)))

(defun run-command (command &optional args)
  "run a shell comamnd and reflect the stdout on screen."
  (let* ((process (sb-ext:run-program command args
                                     :output :stream
                                     :wait nil))
         (output (sb-ext:process-output process)))
    (loop for line = (read-line output nil)
       while line do (format t "~a~%" line))))



(setf *testing* '("1" "2" "3" "4"))
(setf *training* '("5" "6" "7" "8"))


(defun gen-conf (path-id target labeled)
  "Prepare the configuration file"
  (format t "[~a]: ~a~%" path-id target)
  (let ((current-dir (compose-file-name path-id)))
    (run-command "/bin/cp" (list "-f" (compose-file-name *shared-folder* *template*)
                                 (format nil "~a/Prediction.conf" current-dir)))
    (with-open-file (*standard-output* (format nil "~a/Prediction.conf" current-dir)
                           :direction :output
                           :if-exists :append)
      (format t "--estimate ~a~%" path-id))))


(defun first-iteration ()
  (loop for i below 20
       do (gen-conf (thread-name *current-thread*) (format nil "~a" i) (list "123" "456"))))


;;; main
(defun main ()
  (let ((child-threads (loop for i below *path-num*
                          collect (make-thread 
                   (lambda () (first-iteration))
                   :name (format nil "~a" i)))))
    (loop for th in child-threads
       do (join-thread th))))


(main)

ここで、(メイン)では4つのスレッドが作成され、それぞれが実行され(最初の反復)、(最初の反復)では両方を含む(gen-conf)が数回呼び出されます(sb-ext:run-program)およびファイルI/O。

デッドロックはsb-threadの使い方が間違っているためかと思いましたが、SBCLのマニュアルを見ただけでは正しい方法がわかりません。どんな提案も役に立ちます。

ところで、プログラムを実行するには、必要なすべてのディレクトリ/ファイルが作成されているhttp://pages.cs.wisc.edu/~breakds/thread.tar.gzを取得します。

ありがとうございました!

4

0 に答える 0