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.

Acelerar mediante la reducción del número de bucles for.

Actualmente estoy programando en Matlab. Como todos saben, los bucles for son lentos, mientras que Matlab realiza multiplicaciones de matrices de manera muy eficiente. Desafortunadamente, mi código está lleno de bucles for.

Mi código se asemeja a esto:

function FInt = ComputeF(A, B, C, D, E, F, G, H)
    % A es un vector columna real de tamaño [Na, 1].
    % B es un vector columna real de tamaño [Nb, 1].
    % C es un vector columna real de tamaño [Nc, 1].
    % D es un vector columna real de tamaño [Nd, 1].
    % E, F, G son vectores columna reales del mismo tamaño que A.
    % H es un vector columna real del mismo tamaño que A.
    % Esta función evalúa FInt, un tensor de tamaño [Na, Nb, Nc, Nd].

    % Registrando las dimensiones correctas e inicializando FInt
    Na = size(A, 1);
    Nb = size(B, 1);
    Nc = size(C, 1);
    Nd = size(D, 1);
    FInt = zeros(Na, Nb, Nc, Nd);

    % Calculando el tensor FInt
    for na = 1:Na
        for nc = 1:Nc
            for nd = 1:Nd
                % Calculando valores intermedios
                S1 = -((B(:) - C(nc) + E(na)) ./ (2 * sin(D(nd) ./ 2))).^2;
                S2 = (B(:) + C(nc) + F(na)) ./ (2 .* cos(D(nd) ./ 2));
                S3 = (B(:) + C(nc) + G(na)) ./ (2 .* cos(D(nd) ./ 2));
                S4 = H(na) ./ cos(D(nd) ./ 2);
                % Calculando el integrando FInt
                FInt(na, nc, :, nd) = exp(S1) .* (sinh(S2 + 1i * S4) + conj(sinh(S3 + 1i * S4)));
            end
        end
    end
end

Como puedes ver, ya he intentado vectorizar el proceso utilizando : para el vector B, mejorando al menos un poco la velocidad de los cálculos. (¿Por qué B? Por lo general, es el vector más largo).

Mi problema es que las cantidades dependen de tantos índices que no tengo idea de cómo vectorizarlo adecuadamente.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Como experto en IT especializado en Matlab y rendimiento, mi consejo sería intentar utilizar las capacidades de multiplicación de matrices de Matlab para evitar for loops tanto como sea posible. Una forma de hacer esto es mediante la reestructuración de los vectores de entrada en matrices apropiadas y utilizando la multiplicación de matrices para calcular los valores intermedios. Aquí hay un ejemplo de cómo vectorizar el cálculo de los valores S1, S2, S3 y S4 a partir del código original:

    % Reestructurar los vectores de entrada en matrices
    Bmat = repmat(B.', Na, 1); % tamaño [Na, Nb]
    Cmat = repmat(C, 1, Nb); % tamaño [Nc, Nb]
    Emat = repmat(E, 1, Nb); % tamaño [Na, Nb]
    Fmat = repmat(F, 1, Nb); % tamaño [Na, Nb]
    Gmat = repmat(G, 1, Nb); % tamaño [Na, Nb]
    Hmat = repmat(H, 1, Nb); % tamaño [Na, Nb]
    
    % Calcular valores intermedios utilizando la multiplicación de matrices
    S2 = (Bmat + Cmat + Fmat) ./ (2 .* cos(D ./ 2)); % tamaño [Na, Nb, Nd]
    S3 = (Bmat + Cmat + Gmat) ./ (2 .* cos(D ./ 2)); % tamaño [Na, Nb, Nd]
    S4 = Hmat ./ cos(D ./ 2); % tamaño [Na, Nb, Nd]
    S1 = -((Bmat - Cmat + Emat) ./ (2 * sin(D ./ 2))).^2; % tamaño [Na, Nb, Nd]
    

    Con estas matrices intermedias calculadas, luego podemos utilizar la multiplicación de matrices para calcular FInt sin utilizar for loops:

    % Calcular FInt utilizando la multiplicación de matrices
    FInt = zeros(Na, Nb, Nc, Nd);
    for nc = 1:Nc
        FInt(:, :, nc, :) = exp(S1) .* ...
            (sinh(S2 + 1i*S4) + conj(sinh(S3 + 1i*S4)));
    end
    

    Este enfoque aprovecha las eficientes capacidades de multiplicación de matrices de Matlab y puede mejorar significativamente el rendimiento computacional del código.

Comments are closed.