Lispy 方言具有良好的多维数组编程支持

发布于 2024-11-24 15:32:26 字数 195 浏览 4 评论 0原文

是否有任何 Lisp 或方案方言可以很好地支持数组和线性代数操作。我所说的良好支持并不是指 BLAS/LAPACk 的接口,而是语言本身的高效数组原语。如果它能与 Numpy 抗衡,我会认为它是高效的。我听说 Stalin 速度非常快,但我对 lisp 很陌生,不熟悉这种语言中多维数组的语法方便操作和高效表示。指针(没有双关语)将受到深深的赞赏,特别是如果有个人经验的支持。

Are there any Lisp or scheme dialects that have good support for Array and linear algebraic manipulations. By good support I do not mean interfaces to BLAS/LAPACk, but efficient array primitives in the language itself. I would consider it efficient if it can hold its own against Numpy, say. I have heard Stalin to be very fast but I am very new to lisp and not familiar with syntactically convenient manipulation and efficient representation of multi-d arrays in such languages. Pointers (no pun intended) will be deeply appreciated especially if supported with personal experiences.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

萤火眠眠 2024-12-01 15:32:26

标准 Common Lisp 中的数组可以是多维的。

数组字典描述了可用的操作。

CL-USER 12 > (defparameter *a* (make-array '(3 2 4) :initial-element 'foo))
*A*

CL-USER 13 > *a*
#3A(((FOO FOO FOO FOO) (FOO FOO FOO FOO))
    ((FOO FOO FOO FOO) (FOO FOO FOO FOO))
    ((FOO FOO FOO FOO) (FOO FOO FOO FOO)))

CL-USER 14 > (setf (aref *a* 1 1 2) 'bar)
BAR

CL-USER 15 > *a*
#3A(((FOO FOO FOO FOO) (FOO FOO FOO FOO))
    ((FOO FOO FOO FOO) (FOO FOO BAR FOO))
    ((FOO FOO FOO FOO) (FOO FOO FOO FOO)))

CL-USER 16 > (array-dimensions *a*)
(3 2 4)

使用数组时,使用 Common Lisp 的另一个功能可能会很有用:类型声明和编译器优化。 Common Lisp 允许在不声明类型的情况下编写通用代码。但在临界区中,我们可以声明变量、参数、返回值等的类型。然后,可以指示编译器取消某些检查或使用特定于类型的操作。支持的数量取决于编译器。还有更复杂的编译器,如 SBCL、LispWorks 和 Allegro CL,它们支持多种优化。一些编译器还提供大量编译信息。

最后的手段是使用外部函数接口 (FFI) 来调用 C 代码或使用内联汇编程序(某些编译器支持)。

Common Lisp 在标准中默认有 LOOP 宏。它允许表达典型的命令式循环结构。还有一个替代方案,即 ITERATE 宏 - 它对于多维数组可能有一些优势。

另请注意,Lisp 数组有一些不寻常的功能,例如移位数组。它们使用其他一些数组的存储,但可以具有不同的维度布局。

有时编写特殊的宏也很有用,它隐藏了使用数组的样板。如果没有带有类型声明的 Lisp 代码,多维数组和 LOOP 可能会有点大。不使用特殊语言抽象的典型代码示例如下: fft.lisp。

Common Lisp 编译器通常不提供开箱即用的 SIMD 指令或其他形式的数据并行性的特殊使用。可能存在例外情况。

Arrays in standard Common Lisp can be multi-dimensional.

The Array Dictionary describes the available operations.

CL-USER 12 > (defparameter *a* (make-array '(3 2 4) :initial-element 'foo))
*A*

CL-USER 13 > *a*
#3A(((FOO FOO FOO FOO) (FOO FOO FOO FOO))
    ((FOO FOO FOO FOO) (FOO FOO FOO FOO))
    ((FOO FOO FOO FOO) (FOO FOO FOO FOO)))

CL-USER 14 > (setf (aref *a* 1 1 2) 'bar)
BAR

CL-USER 15 > *a*
#3A(((FOO FOO FOO FOO) (FOO FOO FOO FOO))
    ((FOO FOO FOO FOO) (FOO FOO BAR FOO))
    ((FOO FOO FOO FOO) (FOO FOO FOO FOO)))

CL-USER 16 > (array-dimensions *a*)
(3 2 4)

When working with arrays, it may be useful to use another feature of Common Lisp: type declarations and compiler optimizations. Common Lisp allows to write generic code without declaring types. But in critical sections one can declare types for variables, parameters, return values and so on. One then can instruct the compiler to get rid of some checks or to use type specific operations. The amount of support depends on the compiler. There are more sophisticated compilers like SBCL, LispWorks and Allegro CL which support a wide variety of optimizations. Some compilers also give large amounts of compilation information.

A last resort is to use a Foreign Function Interface (FFI) to call C code or to use inline assembler (which is supported by some compilers).

Common Lisp has by default the LOOP macro in the standard. It allows to express the typical imperative looping constructs. There is also an alternative, the ITERATE macro - it may have some advantages for multi-dimensional arrays.

Also note that Lisp arrays have some unusual features like displaced arrays. These use the storage of some other array, but can have a different dimensional layout.

It is also sometimes useful to write special macros, which hide the boilerplate of using arrays. Without that Lisp code with type declarations, multi-dimensional arrays and LOOP can be a bit large. An example for a typical code not using special linguistic abstractions is here: fft.lisp.

Special use of SIMD instructions or other forms of data parallelism are usually not provided out of the box by Common Lisp compilers. Exceptions may exist.

樱娆 2024-12-01 15:32:26

您是否考虑过将 Clojure 与 Incanter 库结合使用?它对矩阵有很好的支持,并且对于图形、数学函数、统计等其他方面有非常高质量的代码。它还对内置的并行性提供了良好的支持。

Have you considered Clojure with the Incanter library? It has good support for matrices and has very high quality code for other things like graphing, mathematical functions, statistics and more. It also has good support for parallelism built right in.

双手揣兜 2024-12-01 15:32:26

Racket(以前称为 PLT 方案)最近获得了不错的多维数组 (math/array )。它们似乎受到 Python NumPy 和 Data Parallel Haskell 的启发。您可能喜欢的一些关键功能:

  • 真正的 N 维超矩形形状
  • 广播(对一个或多个数组进行逐点操作,如 NumPy 中的 UFunc,但更灵活)
  • 切片、转换和重塑(与 NumPy 同等)
  • 数组理解
  • 部分和完全缩减(折叠)
  • 可选的可变性(可变数组允许显式数组集!)
  • 可选的惰性(默认情况下数组是严格的)
  • 可选的类型(必需用于快速代码)

这适用于数组原语。他们碰巧也擅长数学/矩阵。

> (require math/array math/matrix)
> (define arr3d (array-reshape (list->array (range 1 19)) #[2 3 3]))
> arr3d
(array #[#[#[1 2 3] #[4 5 6] #[7 8 9]] #[#[10 11 12] #[13 14 15] #[16 17 18]]])
> (array-map * arr3d arr3d)
(array
 #[#[#[1 4 9]
     #[16 25 36]
     #[49 64 81]]
   #[#[100 121 144]
     #[169 196 225]
     #[256 289 324]]])
> (define m (array-slice-ref arr3d (list 1 ::...)))
> m
(array #[#[10 11 12] #[13 14 15] #[16 17 18]])
> (array-shape m)
'#(3 3)
> (matrix-trace m)
42

math/array 似乎是重新考虑 Scheme Racket 来完成实际任务的一个很好的理由。

Racket (formerly PLT Scheme) has recently got nice multi-dimensional arrays (math/array). They seem to be inspired by Python NumPy and Data Parallel Haskell. Some key features you may like:

  • true N-dimensional hyperrectangular shape
  • broadcasting (pointwise operation on one or more arrays, like UFuncs in NumPy, but more flexible)
  • slicing, transforming and reshaping (on par with NumPy)
  • array comprehensions
  • partial and complete reductions (folds)
  • optional mutability (mutable arrays allow for explicit array-set!)
  • optional laziness (arrays are strict by default)
  • optional typing (required for fast code)

That's for array primitives. They happen to play well with math/matrix too.

> (require math/array math/matrix)
> (define arr3d (array-reshape (list->array (range 1 19)) #[2 3 3]))
> arr3d
(array #[#[#[1 2 3] #[4 5 6] #[7 8 9]] #[#[10 11 12] #[13 14 15] #[16 17 18]]])
> (array-map * arr3d arr3d)
(array
 #[#[#[1 4 9]
     #[16 25 36]
     #[49 64 81]]
   #[#[100 121 144]
     #[169 196 225]
     #[256 289 324]]])
> (define m (array-slice-ref arr3d (list 1 ::...)))
> m
(array #[#[10 11 12] #[13 14 15] #[16 17 18]])
> (array-shape m)
'#(3 3)
> (matrix-trace m)
42

math/array seems like a good reason to reconsider Scheme Racket for practical tasks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文