La transmisión asigna mucha memoria mientras que el bucle for no lo hace.
Si tengo dos variantes siguientes para escribir una parte de mi código y generalmente prefiero una más corta. Esta es la razón por la que me gusta la difusión de puntos en Julia. Sin embargo, este ejemplo muestra que algo está mal con ella.
función test1(A)
n = tamaño(A, 2)
for k in 1:n
for i in k+1:n
A[i, k] /= A[k, k]
end
end
A
end
función test2(A)
n = tamaño(A, 2)
for k in 1:n
A[k+1:n, k] ./= A[k,k]
end
A
end
A = rand(10000,10000)
B = copy(A)
@allocated test1(B) # retorna 0
C = copy(A)
@allocated test2(C) # retorna 401131136
C == B # retorna verdadero
Además, traté de eliminar el azúcar sintáctica y escribí otra función de prueba.
función test3(A)
n = tamaño(A, 2)
for k in 1:n
broadcast!(/, A[k+1:n, k], A[k+1:n, k], A[k,k])
end
A
end
Y esta asigna dos veces más memoria que test2
y… da como resultado un valor incorrecto.
¿Por qué test3
da como resultado un valor incorrecto, y qué hay de malo en la difusión? ¿Hay alguna guía que explique cómo utilizarla?
davy.ai
La razón por la que
test3
devuelve un resultado incorrecto es debido a cómo funciona la transmisión en Julia. Cuando usamos la sintaxis de puntos./=
entest2
, se transmite la operación de división in situ sobre la submatrizA [k + 1: n, k]
por el valor escalarA [k, k]
. El resultado se escribe directamente en la misma submatriz. Esto es eficiente en términos de memoria ya que evita la asignación de matrices temporales.Sin embargo, en
test3
, usamos la funciónbroadcast!
para realizar la misma operación.broadcast!
no modifica la matriz original en su lugar, sino que asigna una nueva matriz temporal para almacenar los valores transmitidos y luego los escribe de vuelta en la matriz original. Esto conduce a la asignación de matrices temporales y, por lo tanto, a un mayor uso de memoria.Para mejorar la eficiencia de la memoria al usar la transmisión, podemos usar la función
broadcast!
de la siguiente manera:Aquí, preasignamos una matriz temporal
temp
para evitar la asignación de matrices temporales dentro del bucle. También usamos la macro@views
para evitar la creación de vistas innecesarias de submatrices. Esta versióntest4
devuelve la salida correcta y tiene la misma asignación de memoria quetest2
.Para obtener más información sobre cómo usar la transmisión de manera eficiente en Julia, puede consultar el Manual oficial de Julia.