2009/7/6 Jeronimo Pellegrini <[email protected]> > > On Mon, Jul 06, 2009 at 12:26:22AM -0300, Gustavo wrote: > > Olá pessoal da lista, > > Olá -- boa madrugada!
Olá! Bom dia! > > > > 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. Verdade! Você tem razão, adjust-array funciona com qualquer array, embora: cl-user> (make-array 20) #(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) cl-user> (eq * (adjust-array * 30)) nil Aliás, acho que essa foi uma excelente escolha pelo pessoal que fez a spec! > 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. Na verdade, não é exatamente assim. A specificação diz que uma array que não é ajustável, não tem fill-pointer e sem "overlap" é uma simples array, mas que é "implementation-dependent" se a recíproca é verdadeira (em outras palavras, uma implementação pode considerar todas as arrays como sendo simple-arrays). De acordo com o spec (na especificação sobre o tipo SIMPLE-ARRAY): "It is *implementation-dependent*<http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_i.htm#implementation-dependent>whether *displaced arrays*<http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_d.htm#displaced_array>, *vectors*<http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_v.htm#vector>with *fill pointers*<http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_f.htm#fill_pointer>, or arrays that are *actually adjustable*<http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_a.htm#actually_adjustable>are *simple arrays*<http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_s.htm#simple_array>. " Aliás, é até possível que, numa implementação específica, todas as arrays sejam ajustáveis por padrão. Porém, na minha intuição, apenas o "overlap" é que pode dificultar a otimização (especialmente overlap de arrays multi-dimensionais), então eu imaginava que o sbcl, sendo esperto, só não iria considerar como sendo simple-arrays as arrays com overlap. Bom, enfim, não fui eu quem fiz o sbcl, então não vou reclamar ;) > > > > 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. Isso é bom :) E o bom também é que, se alguma implementação considerar todas as arrays como sendo ajustáveis, usar o adjust-array fará o meu projeto acabar automaticamente usando essa vantagem (mas será que alguma implementação faz isso? Nem o clisp nem o ecl fazem isso). De qualquer forma, é o que eu preciso. Os ajustes das arrays não devem ser muito frequentes mesmo (de acordo com a lei da probabilidade), então esse problema de tempo do ajuste não vai importar muito. Obrigado pela resposta, ajudou muito :) > > > 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 -~----------~----~----~----~------~----~------~--~---
