es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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?

Tags:  , ,

Answer

  1. Avatar for 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 ./= en test2, se transmite la operación de división in situ sobre la submatriz A [k + 1: n, k] por el valor escalar A [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ón broadcast! 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:

    function test4(A)
        n = size(A, 2)
        temp = similar(A, n-1) # pre-asignar una matriz temporal
        for k in 1:n
            @views temp[1:n-k] .= A[k+1:n, k] ./ A[k, k]
            @views A[k+1:n, k] .= temp[1:n-k] # escribir de vuelta en la matriz original
        end
        A
    end
    

    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ón test4 devuelve la salida correcta y tiene la misma asignación de memoria que test2.

    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.

Comments are closed.