On Mon, Jul 06, 2009 at 12:26:22AM -0300, Gustavo wrote:
> Olá pessoal da lista,
Olá -- boa madrugada!
> Acabei de fazer uma descoberta que vai contra a minha intuição.
>
> Estava testando eficiência com arrays de inteiros (de (unsigned-byte 64)
> para ser mais exato) e descobri que arrays não ajustáveis são 10 vezes mais
> eficientes que as ajustáveis! Eu imaginava que não deveria haver diferença,
> porque, por exemplo, em C, se você aloca um array dinamicamente (com
> malloc), esse array é automaticamente ajustável (com realloc).
Mas o adjust-array funciona com arrays não-ajustáveis. Se não me engano,
você não tem mais garantia que o array será o mesmo objeto:
(EQ array-antigo array-novo)
pode ser NIL. Este é o código que uso para ajustar arrays no
Spartns [0]:
(defun robust-adjust-array (array size &key (element-type nil))
"Adjusts the size of an array, setting it to the new one. Also works
around an issue with Allegro Common Lisp: in ACL, when you call
adjust-array on a non-adjustable array, the resulting array is not
necessarily of the same type. It is not a SIMPLE-ARRAY
anymore. Dependig on how you try to fix it, you may end up with an
array whose element-type is T. So, this is a method for resizing an
array and keeping the same array type.
Yes, we want SIMPLE-ARRAYs because access is faster. But we also want to
adjust them, even if adjusting is slow."
(let ((type (if (null element-type)
`(array-element-type ,array)
element-type)))
(setf array
#-allegro (adjust-array array size :element-type type)
#+allegro (coerce (adjust-array array size :element-type type
:adjustable nil)
`(simple-array ,type *)))
array))
Note que o código não necessariamente altera seu array; ele retorna outro!
> (setf a (make-array 5 :element-type 'fixnum))
> a
#(0 0 0 0 0)
> (type-of a)
(SIMPLE-ARRAY FIXNUM (5))
> (setf b (robust-adjust-array a 10))
> (type-of a)
(SIMPLE-ARRAY FIXNUM (5))
> a
#(0 0 0 0 0)
> b
#(0 0 0 0 0 0 0 0 0 0)
> (type-of b)
(SIMPLE-ARRAY FIXNUM (10))
> Também descobri que, felizmente, você pode declarar uma array como sendo do
> tipo simple-array para poder aproveitar essa eficiência (simple-arrays são
> arrays não-ajustáveis, sem fill-pointer e sem "displacement" (i.e. arrays
> que são criadas sem passar o argumento :displace-to)).
>
> A única explicação que eu consigo pensar é que, se uma array ajustável é
> criada, o sbcl identifica seu tipo como sendo uma array "normal" (ao invés
> de identificá-la como uma simple-array), o que faz com que ele não consiga
> otimizar as chamadas para aref porque o tipo array "normal" não diferencia
> arrays com "displacement" ou sem "displacement".
Não só o SBCL; isso está previsto no padrão ANSI. Um simple-array é
aquele que não é ajustável, sem overlap com outro, e sem fill-pointer.
E a idéia é justamente permitir otimizações.
> Poder
> usar arrays ajustáveis sem problemas com a eficiência iria quebrar o galho
> no que eu pretendo fazer (embora não seja totalmente necessário, mas vou ter
> que sair copiando uma parte da array).
Do modo como eu propus pode ser que *o ajuste* fique lento, mas o acesso é
tão rápido quanto em C.
J.
[0] http://aleph0.info/spartns
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Lisp-br" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/lisp-br?hl=en
-~----------~----~----~----~------~----~------~--~---