Параллельное сэмплирование Lisp - PullRequest
2 голосов
/ 05 марта 2012

Предположим, что я хочу сделать выборки из некоторого распределения вероятностей. В приведенном ниже примере я рисую несколько равномерно распределенных значений от 0 до 1 10000 раз. Меня не волнует порядок случайных выборок в векторе, ведь они случайные.

(setf my-vec (make-sequence 'vector 10000 :initial-element 0))
(loop :for i :from 0 :to 9999 :do
   (setf (svref my-vec i) (random 1.0)))

У меня есть многоядерный компьютер, и я хочу реализовать вышеуказанный код параллельно. (то есть, предполагая, что у меня есть 4 ядра, выборка 2500 в одном ядре и в конце добавление всех выборок к одному вектору. Ранее я спрашивал о Common Lisp Parallel Programming Вот. Предполагая, что я полностью новичок в CL и программировании в целом, каким должен быть мой подход к этой проблеме? Мне не требуются дополнительные характеристики при распараллеливании, я просто хочу равномерно распределить вычислительную нагрузку выборки по ядрам машины. Если бы вы могли указать некоторые шаги для распараллеливания или некоторые онлайн-учебные материалы, которые я мог бы извлечь из этого, было бы очень приятно. Заранее большое спасибо.

1 Ответ

4 голосов
/ 06 марта 2012

Вам нужна реализация Common Lisp, которая поддерживает несколько ядер.Примерами являются CCL, LispWorks и на некоторых платформах (IIRC) SBCL.

Ниже приведен простой пример использования LispWorks 6.1 и его возможностей многопроцессорной обработки.Он использует конструкцию, называемую барьер .Процессы ждут на барьере, пока не наступит достаточное количество процессов.Здесь это означает, что достаточное количество потоков завершило свою векторную инициализацию.

Типичная функция для запуска потока - PROCESS-RUN-FUNCTION.

(defun make-random-vector (&key (size 10000) (n-threads 4))
  (let ((vector  (make-sequence 'vector size :initial-element 0))
        (barrier (mp:make-barrier (1+ n-threads)))
        (delta   (truncate size n-threads)))
    (loop for i below n-threads
          do (mp:process-run-function
              "init"
              nil
              (lambda (barrier vector start end)
                (loop for i from start below end do
                      (setf (svref vector i) (random 1.0)))
                (mp:barrier-wait barrier :pass-through t))
              barrier
              vector
              (* i delta)
              (+ delta (* i delta))))
    (mp:barrier-wait barrier)
    vector))
...