Хобрук: Ваш путь к мастерству в программировании

Матричное умножение с использованием BLAS из Common Lisp

Допустим, у меня есть две матрицы (в виде массива Common Lisp) foo и bar такие, что:

(defvar foo #2A((2 1 6) (7 3 4)))
(defvar bar #2A((3 1) (6 5) (2 3)))

Я хотел бы выполнить матричное умножение, используя BLAS без использования оболочек, таких как Matlisp, GSLL, LLA и т. д. так что я получаю массив с результатом:

#2A((24 25) (47 34))

Какие шаги я должен предпринять для выполнения такой операции?

Насколько я понимаю, я должен вызвать функцию умножения матриц BLAS из REPL и передать ей свои аргументы foo и bar.

В R я могу легко сделать это так:

foo %*% bar

Как я могу сделать это в Common Lisp?

Отказ от ответственности: 1) я использую SBCL 2) я не опытный программист


Ответы:


1

Вот идеальный ответ, который я искал. Кредиты Мирославу Урбанеку из Карлова университета в Праге.

«Вот основная идея. Я нахожу функцию, которую хочу использовать, в BLAS/LAPACK. В случае умножения матриц это DGEMM. , треугольный и т. д.), а «ММ» означает умножение матриц. Документация находится здесь:

http://www.netlib.org/lapack/explore-html/d7/d2b/dgemm_8f.html

Затем я определяю инопланетную процедуру, используя SBCL FFI. Я передаю массив Lisp напрямую, используя некоторые специальные функции SBCL. Массивы Lisp должны быть созданы с опцией :element-type 'double-float.

Важным моментом является то, что SBCL хранит элементы массива в порядке строк, аналогично C. Fortran использует порядок столбцов. Это эффективно соответствует транспонированным матрицам. Поэтому порядок матриц и их размерности должны быть изменены при вызове DGEMM из Лиспа».

;; Matrix multiplication in SBCL using BLAS
;; Miroslav Urbanek <[email protected]>

(load-shared-object "libblas.so.3")

(declaim (inline dgemm))

(define-alien-routine ("dgemm_" dgemm) void
  (transa c-string)
  (transb c-string)
  (m int :copy)
  (n int :copy)
  (k int :copy)
  (alpha double :copy)
  (a (* double))
  (lda int :copy)
  (b (* double))
  (ldb int :copy)
  (beta double :copy)
  (c (* double))
  (ldc int :copy))

(defun pointer (array)
  (sap-alien (sb-sys:vector-sap (array-storage-vector array)) (* double)))

(defun mm (a b)
  (unless (= (array-dimension a 1) (array-dimension b 0))
    (error "Matrix dimensions do not match."))
  (let* ((m (array-dimension a 0))
     (n (array-dimension b 1))
     (k (array-dimension a 1))
     (c (make-array (list m n) :element-type 'double-float)))
    (sb-sys:with-pinned-objects (a b c)
      (dgemm "n" "n" n m k 1d0 (pointer b) n (pointer a) k 0d0 (pointer c) n))
    c))

(defparameter a (make-array '(2 3) :element-type 'double-float :initial-contents '((2d0 1d0 6d0) (7d0 3d0 4d0))))
(defparameter b (make-array '(3 2) :element-type 'double-float :initial-contents '((3d0 1d0) (6d0 5d0) (2d0 3d0))))

(format t "a = ~A~%b = ~A~%" a b)

(defparameter c (mm a b))
26.06.2015

2

В R вы используете оболочку R. Вы не можете избежать использования "обертки". Таким образом, вы должны использовать то, что лучше всего подходит вам.

Извините, если это не очень полезно, но так обстоят дела.

Марко

27.04.2015
  • В настоящее время я понимаю, что вам нужна некоторая привязка внешнего интерфейса функции, чтобы обеспечить связь между функцией BLAS и ее вызовом из Common Lisp. Если я правильно понимаю, в этом смысле да, вам нужна оболочка. Если перефразировать мой вопрос с большей точностью, это приведет к следующему: как я могу напрямую использовать ffi без использования какой-либо другой библиотеки Lisp более высокого уровня, такой как Matlisp и т. Д.? Я пытаюсь понять, как выполнить умножение матриц на двух массивах CL foo и bar или вычислить ковариационную матрицу на некотором массиве baz, используя уже существующие функции BLAS. 07.05.2015
  • Новые материалы

    Решения DBA Metrix
    DBA Metrix Solutions предоставляет удаленного администратора базы данных (DBA), который несет ответственность за внедрение, обслуживание, настройку, восстановление базы данных, а также другие..

    Начало работы с Блум
    Обзор и Codelab для генерации текста с помощью Bloom Оглавление Что такое Блум? Некоторые предостережения Настройка среды Скачивание предварительно обученного токенизатора и модели..

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...