Estaba leyendo a useful post at WRI blog on improving speed of code, y necesito ayuda para entender esto.diferencia de velocidad en hacer una tabla
comparar estas velocidades
Timing[
tbl = Table[i + j, {i, 1, 1000}, {j, 1, 1000}];
]
{0.031, Null}
y
Timing[
a = 1000;
tbl = Table[i + j, {i, 1, a}, {j, 1, a}];
]
{0.422, Null}
Por lo tanto, es mucho más rápido si se pone el valor real para el límite interior de la propia tabla vs exterior. La explicación para esto, que estoy seguro es correcta, pero necesito ayuda para entender, es que Table
se compila si su límite es numérico vs. no, esto es porque sus atributos son HoldAll
.
Pero mi pregunta es: ¿Cómo funcionaría lo anterior, porque los límites a Table
deben, en un punto, convertirse en numéricos de todos modos? No puedo escribir
Clear[a]
tbl = Table[i + j, {i, 1, a}, {j, 1, a}]
Lo anterior da un error.
Así que, para mí, la escritura a=1000
fuera Table
vs. dentro, debería haber hecho ninguna diferencia, ya que sin a
tener un valor numérico, Table[]
no se puede hacer nada. Entonces, la sustitución de a
por el número 1000 debe ocurrir en un punto dado por el evaluador antes de que Table[]
pueda hacer algo útil, ¿no es así?
En otras palabras, lo que Table
debería ver, finalmente, es {i, 1, 1000}, {j, 1, 1000}
en ambos casos.
Por lo tanto, la forma en que pensé que esto sucedería es la siguiente:
- Evaluador reemplaza por
a
1000 en los argumentos de la tabla - Evaluador llama
Table
con el resultado, que ahora es todo lo numérico. - Table Compila y ahora funciona más rápido.
Pero lo que parece suceder es otra cosa. (debido a HoldAll
?)
- La tabla toma sus argumentos, tal como está. Como tiene HoldAll, entonces ve
a
y no 1000. - No llama a Compilar ya que sus argumentos no son todos los números.
- Ahora generar una tabla con el límite
a
, Evaluador evalúaa
a 1000 - se genera la tabla ahora todos los límites son numéricos, pero más lento ahora ya que el código no se compila.
pregunta es: ¿El tipo más arriba de lo que sucede? ¿Podría alguien explicar los pasos que habrían sucedido para explicar esta diferencia en el tiempo?
Además, ¿cómo se asegurará de que la tabla se compila en ambos casos en el ejemplo anterior, incluso si se utiliza una variable para el límite?No siempre es posible codificar los números para los límites de la tabla, pero a veces se deben usar variables para estos. ¿Debería uno usar explícitamente el comando Compile
? (No uso Compile
directamente, ya que asumí que se hace automáticamente cuando es necesario).
edición (1)
En respuesta a mensaje por Mike continuación en encontrar ninguna diferencia en el tiempo cuando se utiliza una llamada.
ClearAll[tblFunc];
Timing[a = 1000;
tblFunc[a_] := Table[i + j, {i, 1, a}, {j, 1, a}];
Developer`PackedArrayQ[tblFunc[a]]
]
da
{0.031, True}
Pero eso es porque a
es ahora el número 1000
dentro de la función, una vez que se llama. Como M pasa cosas por VALOR.
Si forzamos la llamada a ser por referencia, de manera que a
se deja sin evaluar, entonces tenemos
ClearAll[tblFunc];
Timing[a = 1000;
tblFunc[a_] := Table[i + j, {i, 1, a}, {j, 1, a}];
Developer`PackedArrayQ[tblFunc[[email protected]]]
]
Ahora vemos el resultado esperado, ya que ahora a
sigue siendo simbólica dentro de la función, estamos volver al punto uno, y ahora es lento, ya que no está empaquetado. Y dado que no está empaquetado, no se usa Compilar.
{0.437, False}
edición (2) Gracias a todos por las respuestas, creo que aprendí de adjudicar de ellos.
Aquí hay un resumen ejecutivo, solo para asegurarse de que todo estaba bien.
edición (3)
Aquí están los enlaces especialmente he relacionados con consejos a utilizar para hacer el código Mathematica funciona más rápido.
- http://library.wolfram.com/howtos/faster/
- http://blog.wolfram.com/2011/12/07/10-tips-for-writing-fast-mathematica-code/
- https://stackoverflow.com/questions/4721171/performance-tuning-in-mathematica
- Using Array and Table Functions in Mathematica. Which is best when
Tenga en cuenta que puede tener cosas como 'Tabla [i + j, {i, 1, 1000}, {j, 1, i}]', que es una razón para que 'Table' no se pueda compilar cuando no se hayan definido los límites todo es numérico –
Pregunta relacionada: http://stackoverflow.com/questions/5764774/using-array-and-table-functions-in-mathematica-whichthis-best-when/ –
@David Estoy de acuerdo con su afirmación, solo quiero Haga hincapié en que la verdadera razón por la cual 'Table' es lenta para los iteradores simbólicos parece ser que no puede determinar si el resultado será una matriz * rectangular * y, por lo tanto, no puede usar matrices empaquetadas. El hecho de que no puede usar 'Compile' se deduce de esto, porque las matrices empaquetadas son las que le dan a' Compile' sus ganancias de eficiencia (al menos cuando se compila con el objetivo MVM, que es lo que creo que está ocurriendo en la autocompilación). –