Estou usando o Tatu para fazer multiplicações de matriz muito intensivas com comprimentos laterais , onde pode ser de até 20 ou mais. Estou usando o Armadillo com o OpenBLAS para multiplicação de matrizes, o que parece estar fazendo um trabalho muito bom em núcleos paralelos, exceto que tenho um problema com o formalismo da multiplicação no Armadillo para super otimização de desempenho. n
Digamos que eu tenho um loop no seguinte formato:
arma::cx_mat stateMatrix, evolutionMatrix; //armadillo complex matrix type
for(double t = t0; t < t1; t += 1/sampleRate)
{
...
stateMatrix = evolutionMatrix*stateMatrix;
...
}
No C ++ fundamental, acho que o problema aqui é que o C ++ alocará um novo objeto de cx_mat
para armazenar evolutionMatrix*stateMatrix
e, em seguida, copie o novo objeto para stateMatrix
with operator=()
. Isso é muito, muito ineficiente. É sabido que retornar classes complexas de grandes tipos de dados é uma má ideia, certo?
A maneira como vejo isso indo de maneira mais eficiente é com uma função que faz a multiplicação na forma:
void multiply(const cx_mat& mat1, const cx_mat& mat2, cx_mat& output)
{
... //multiplication of mat1 and mat2 and then store it in output
}
Dessa forma, não é necessário copiar objetos enormes com valor de retorno, e a saída não precisa ser realocada a cada multiplicação.
A pergunta : como posso encontrar um compromisso, no qual eu possa usar o Armadillo para multiplicação com sua bela interface do BLAS, e fazer isso de forma eficiente sem precisar recriar objetos de matriz e copiá-los a cada operação?
Isso não é um problema de implementação no Tatu?
stateMatrix = evolutionMatrix*stateMatrix
não fará nenhuma cópia. Em vez disso, o Armadillo faz uma alteração elegante no ponteiro da memória. A nova memória para o resultado ainda será alocada (não há como contornar isso), mas, em vez de copiar, a stateMatrix
matriz simplesmente usará a nova memória e descartará a memória antiga.