有什么方法可以在 Common Lisp 中将扁平结构数组分配为 C?
Any ways to allocate flattened array of structure as C in Common Lisp?
是否有任何方法可以在 Common Lisp 中分配扁平结构数组 (AOS) 以提高效率?
我的意思是下面的 C 等价物。
typedef struct {
int x;
float y;
double z;
} foo_t;
#define SIZE 1000000
void bar()
{
foo_t *f = malloc( sizeof( foo_t ) * SIZE );
do_something_with( f );
}
通常在 Common Lisp 中,引用结构对象的指针数组用于表示这样的数据结构。
(defstruct foo
(x 0 :type fixnum)
(y 0.0 :type single-float)
(z 0d0 :type double-float))
(let* ((size 1000000)
(f (make-array size :element-type 'foo
:initial-contents (loop repeat size
collect (make-foo)))))
(do-something-with f))
当结构只有一种类型时,可以使用简单数组以命令方式获得非常高效的性能,尽管简单数组只接受一种类型作为其元素类型。
; (defstruct vertex
; (x 0d0 :type double-float)
; (y 0d0 :type double-float)
; (z 0d0 :type double-float))
(defun make-vertex-array (n)
(make-array n :element-type 'double-float :initial-element 0d0))
(defmacro vertex-x (ary i)
`(aref ,ary (+ (* ,i 3) 0)))
(defmacro vertex-y (ary i)
`(aref ,ary (+ (* ,i 3) 1)))
(defmacro vertex-z (ary i)
`(aref ,ary (+ (* ,i 3) 2)))
(let* ((size 1000000)
(ary (make-vertex-array 100))
(do-something-with ary))
我想听听关于如何对具有多种元素类型的结构进行此类操作。
如果我对你的理解是正确的,你想要一个结构作为元素类型,以高效和整洁地访问结构的参数?为什么不直接这样做 - 这是否 'efficient' 取决于实现,你将无法通过软件提供的优化选项对它产生更大的影响。
(defstruct foo
(x 0 :type fixnum)
(y 0.0 :type single-float)
(z 0d0 :type single-float))
(defun make-vertex-array (size)
(make-array size :element-type 'foo :initial-contents (loop repeat size
collect (make-foo :x 0 :y 0.0 :z 0.0))))
(defparameter *test*
(make-vertex-array 100))
(defmacro vertex-x (array i)
`(foo-x (aref ,array ,i)))
(defmacro vertex-y (array i)
`(foo-y (aref ,array ,i)))
(defmacro vertex-z (array i)
`(foo-z (aref ,array ,i)))
(setf (vertex-x *test* 5) 4)
(setf (aref *test* 10) (make-foo :x 2 :y 0.0 :z 0.0))
(FORMAT T "~a~%" *test*)
>the array will be printed an you can see the changes
(type-of *test*)
>(SIMPLE-VECTOR 100)
(type-of (make-array 100 :element-type 'integer))
>(SIMPLE-VECTOR 100)
根据CLHS
SIMPLE-VECTOR: The type of a vector that is not displaced to another array, has no
fill pointer, is not expressly adjustable and is able to hold elements
of any type is a subtype of type simple-vector.
Any one-dimensional array is a vector.
现在谈谈您的效率问题。我没有做基准测试,所以我必须坚持使用手册。不过好像SBCL应该优化一下。
... the original CMUCL manual is still 95+% correct for the SBCL ...
Vectors (one dimensional arrays) are particularly useful, since in
addition to their obvious array-like applications, they are also well
suited to representing sequences. In comparison to a list
representation, vectors are faster to access and take up between two
and sixty-four times less space (depending on the element type.) As
with arbitrary arrays, the compiler needs to know that vectors are not
complex, so you should use simple-string in preference to string, etc.
因此后台正在进行一些优化。但是,这是否涉及不使用引用并直接在数组中分配结构取决于 SBCL,您将无法影响它。
标准 Common Lisp 不提供这样的功能。我不知道实现高效结构数组的实现,其中结构在数组中分配。实现 可能 为某些结构实现有效的内存分配,但通常不会为结构向量实现。
这会给垃圾收集器带来挑战。当没有对它的实时引用时,通常一个对象是垃圾。如果我们允许在数组内部分配结构,那么如果没有对它的引用并且没有对它的引用(对数组内部的任何结构),该数组将是垃圾。
可能有提供类似功能的库 (http://cliki.net/data%20formats)。
通常有 FFI(外部函数接口)功能可以处理记录数组,或者可以使用 FFI 构建它们。
是否有任何方法可以在 Common Lisp 中分配扁平结构数组 (AOS) 以提高效率?
我的意思是下面的 C 等价物。
typedef struct {
int x;
float y;
double z;
} foo_t;
#define SIZE 1000000
void bar()
{
foo_t *f = malloc( sizeof( foo_t ) * SIZE );
do_something_with( f );
}
通常在 Common Lisp 中,引用结构对象的指针数组用于表示这样的数据结构。
(defstruct foo
(x 0 :type fixnum)
(y 0.0 :type single-float)
(z 0d0 :type double-float))
(let* ((size 1000000)
(f (make-array size :element-type 'foo
:initial-contents (loop repeat size
collect (make-foo)))))
(do-something-with f))
当结构只有一种类型时,可以使用简单数组以命令方式获得非常高效的性能,尽管简单数组只接受一种类型作为其元素类型。
; (defstruct vertex
; (x 0d0 :type double-float)
; (y 0d0 :type double-float)
; (z 0d0 :type double-float))
(defun make-vertex-array (n)
(make-array n :element-type 'double-float :initial-element 0d0))
(defmacro vertex-x (ary i)
`(aref ,ary (+ (* ,i 3) 0)))
(defmacro vertex-y (ary i)
`(aref ,ary (+ (* ,i 3) 1)))
(defmacro vertex-z (ary i)
`(aref ,ary (+ (* ,i 3) 2)))
(let* ((size 1000000)
(ary (make-vertex-array 100))
(do-something-with ary))
我想听听关于如何对具有多种元素类型的结构进行此类操作。
如果我对你的理解是正确的,你想要一个结构作为元素类型,以高效和整洁地访问结构的参数?为什么不直接这样做 - 这是否 'efficient' 取决于实现,你将无法通过软件提供的优化选项对它产生更大的影响。
(defstruct foo
(x 0 :type fixnum)
(y 0.0 :type single-float)
(z 0d0 :type single-float))
(defun make-vertex-array (size)
(make-array size :element-type 'foo :initial-contents (loop repeat size
collect (make-foo :x 0 :y 0.0 :z 0.0))))
(defparameter *test*
(make-vertex-array 100))
(defmacro vertex-x (array i)
`(foo-x (aref ,array ,i)))
(defmacro vertex-y (array i)
`(foo-y (aref ,array ,i)))
(defmacro vertex-z (array i)
`(foo-z (aref ,array ,i)))
(setf (vertex-x *test* 5) 4)
(setf (aref *test* 10) (make-foo :x 2 :y 0.0 :z 0.0))
(FORMAT T "~a~%" *test*)
>the array will be printed an you can see the changes
(type-of *test*)
>(SIMPLE-VECTOR 100)
(type-of (make-array 100 :element-type 'integer))
>(SIMPLE-VECTOR 100)
根据CLHS
SIMPLE-VECTOR: The type of a vector that is not displaced to another array, has no fill pointer, is not expressly adjustable and is able to hold elements of any type is a subtype of type simple-vector.
Any one-dimensional array is a vector.
现在谈谈您的效率问题。我没有做基准测试,所以我必须坚持使用手册。不过好像SBCL应该优化一下。
... the original CMUCL manual is still 95+% correct for the SBCL ...
Vectors (one dimensional arrays) are particularly useful, since in addition to their obvious array-like applications, they are also well suited to representing sequences. In comparison to a list representation, vectors are faster to access and take up between two and sixty-four times less space (depending on the element type.) As with arbitrary arrays, the compiler needs to know that vectors are not complex, so you should use simple-string in preference to string, etc.
因此后台正在进行一些优化。但是,这是否涉及不使用引用并直接在数组中分配结构取决于 SBCL,您将无法影响它。
标准 Common Lisp 不提供这样的功能。我不知道实现高效结构数组的实现,其中结构在数组中分配。实现 可能 为某些结构实现有效的内存分配,但通常不会为结构向量实现。
这会给垃圾收集器带来挑战。当没有对它的实时引用时,通常一个对象是垃圾。如果我们允许在数组内部分配结构,那么如果没有对它的引用并且没有对它的引用(对数组内部的任何结构),该数组将是垃圾。
可能有提供类似功能的库 (http://cliki.net/data%20formats)。
通常有 FFI(外部函数接口)功能可以处理记录数组,或者可以使用 FFI 构建它们。