Estoy usando Armadillo para hacer multiplicaciones matriciales muy intensas con longitudes laterales , donde puede ser de hasta 20 o incluso más. Estoy usando Armadillo con OpenBLAS para la multiplicación de matrices, que parece estar haciendo un muy buen trabajo en núcleos paralelos, excepto que tengo un problema con el formalismo de la multiplicación en Armadillo para una súper optimización del rendimiento.
Digamos que tengo un bucle en la siguiente forma:
arma::cx_mat stateMatrix, evolutionMatrix; //armadillo complex matrix type
for(double t = t0; t < t1; t += 1/sampleRate)
{
...
stateMatrix = evolutionMatrix*stateMatrix;
...
}
En C ++ fundamental, el problema aquí es que C ++ asignará un nuevo objeto de cx_mat
almacenar evolutionMatrix*stateMatrix
y luego copiará el nuevo objeto stateMatrix
con operator=()
. Esto es muy, muy ineficiente. Es bien sabido que devolver clases complejas de tipos de datos grandes es una mala idea, ¿verdad?
La forma en que veo que esto es más eficiente es con una función que realiza la multiplicación en la 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
}
De esta manera, uno no tiene que copiar objetos enormes con valor de retorno, y la salida no tiene que reasignarse con cada multiplicación.
La pregunta : ¿Cómo puedo encontrar un compromiso, en el que pueda usar Armadillo para la multiplicación con su agradable interfaz de BLAS, y hacer esto de manera eficiente sin tener que recrear objetos de matriz y copiarlos con cada operación?
¿No es este un problema de implementación en Armadillo?
stateMatrix = evolutionMatrix*stateMatrix
no hará ningún tipo de copia. En cambio, Armadillo hace un elegante cambio de puntero de memoria. Todavía se asignará nueva memoria para el resultado (no hay forma de evitarlo), pero en lugar de copiar, la stateMatrix
matriz simplemente usará la nueva memoria y descartará la memoria anterior.