使用Common Lisp中的BLAS进行矩阵乘法

时间:2015-04-23 11:46:31

标签: common-lisp matrix-multiplication blas sbcl

让我们说我有两个矩阵(以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))

我应该采取哪些步骤来执行此类操作?

我的理解是我应该从REPL调用BLAS矩阵乘法函数并将其传递给我的参数foo和bar。

在R中,我可以轻松地这样做:

foo %*% bar

我怎么能在Common Lisp中做到这一点?

声明: 1)我使用SBCL 2)我不是一位经验丰富的计算机科学家

2 个答案:

答案 0 :(得分:3)

这是我正在寻找的完美答案。来自布拉格查理大学的Miroslav Urbanek的学分。

“这是基本的想法。我找到了一个我想要使用的功能 BLAS / LAPACK。在矩阵乘法的情况下,它是DGEMM。 “D”代表 对于双浮点,“GE”代表一般矩阵(没有特殊的 形状像对称,三角形等),“MM”代表矩阵 乘法。文档在这里:

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

然后我使用SBCL FFI定义一个外星人例程。我通过Lisp数组 直接使用一些特殊的SBCL函数。 Lisp数组必须是 使用选项创建:element-type'double-float。

重要的一点是SBCL将数组元素存储在row-major中 顺序,类似于C. Fortran使用列主要顺序。这个 有效地对应于转置矩阵。矩阵的顺序 因此,在调用DGEMM时必须更改它们的尺寸 口齿不清。“

;; Matrix multiplication in SBCL using BLAS
;; Miroslav Urbanek <mu@miroslavurbanek.com>

(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))

答案 1 :(得分:2)

在R中,您正在使用R包装器。你无法避免使用“包装”。所以你应该使用最适合你的。

对不起,如果这没有多大帮助,但事情就是这样。