¿Cuál es la forma más eficiente de obtener una matriz dispersa compleja de mi código Fortran a PETSc? Entiendo que esto depende del problema, por lo que traté de dar tantos detalles relevantes como sea posible a continuación.
He estado jugando con el solucionador de valores propios FEAST [1] para problemas del tipo , la dimensión de las matrices y es , y casi todo el tiempo lo paso resolviendo complejo Sistema lineal con M0 a la derecha. N es grande (número de funciones básicas de FE, en 3D), M0 es pequeño (en mi caso, estoy interesado en M0 ~ 20). Las matrices y son reales, simétricas y escasas, y el problema complejo que debe resolverse es , dondeEs un número complejo. El autor de FEAST parece sugerir que la precisión de la solución a este sistema lineal no tiene que ser muy alta para obtener valores y vectores propios de alta precisión, por lo que algunos solucionadores iterativos rápidos podrían ser una gran solución para esto.
Hasta ahora solo he estado usando Lapack para el sistema complejo, y eso funciona muy bien para en mi computadora. Para más grande , todavía no sé cuál es el mejor solucionador, así que solo quería usar PETSc y jugar con los solucionadores iterativos allí.
Escribí un controlador C simple, y lo llamo desde Fortran, vea [2] para todo el código, pero el problema es solo con esta parte (actualización: he puesto aquí todas las líneas para crear la matriz, como acabo de darme cuenta que esto es relevante):
ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr);
ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,n,n);CHKERRQ(ierr);
ierr = MatSetFromOptions(A);CHKERRQ(ierr);
ierr = MatSetOption(A,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
ierr = MatSetUp(A);CHKERRQ(ierr);
for (i=0; i<n; i++) col[i] = i;
ierr = MatSetValues(A,n,col,n,col,A_,INSERT_VALUES);CHKERRQ(ierr);
Lo cual es extremadamente lento (es decir, para N ~ 1500, esto toma tal vez 2 segundos, mientras que resolverlo es inmediato), de hecho, la MatSetValues
línea toma casi el 100% de todo el tiempo para el cálculo del valor propio completo ... La matriz A_ es un Matriz 2D que proviene de Fortran. Traté de desactivar el MAT_IGNORE_ZERO_ENTRIES
pero no hizo ninguna diferencia. Entonces, creo que el problema simplemente es que incluso para N moderado como 1500, necesito usar un formato de matriz disperso, ¿es correcto?
Así que implementé el formato CSR en mi código Fortran para las matrices y B (o para la z A - B ) y ahora estoy tratando de descubrir cómo dárselo eficientemente a PETSc. Por ahora, solo quiero que algo funcione secuencialmente, que supere a Lapack. ¿Debo usar la función para esto?MatCreateSeqAIJWithArrays
¿Es esta la forma más eficiente de hacer eso? Dado que las matrices y B no cambian, solo el número complejo z cambia en el algoritmo FEAST, y en un cálculo FE, creo que tanto A como B tienen la misma estructura dispersa, uno probablemente puede mejorar las cosas preasignando el estructura dispersa y luego evaluar rápidamente z A x - B x en cada iteración FEAST ( A x , B x son las matrices de valores del formato CSR), puedo hacer esto fácilmente en Fortran, pero tal vez sea lento llamar siempreMatCreateSeqAIJWithArrays
, Por lo que podría ser más rápido para hacer todo esto en PETSc vez las matrices y B se transfieren a través.
Me gustaría saber si este enfoque de RSE para este problema es correcto o si lo estoy haciendo mal (claramente mi enfoque original con el MatSetValues
no es óptimo). Gracias por cualquier consejo.
[1] http://www.ecs.umass.edu/~polizzi/feast/
[2] https://github.com/certik/hfsolver/pull/14
[3] http://www.mcs.anl.gov/petsc/petsc-3.1/docs/manualpages/Mat/MatCreateSeqAIJWithArrays.html
MatSetValues()
. Para traducir una matriz existente, ¿no es más rápido simplemente llamarMatCreateSeqAIJWithArrays
una vez en lugar de llamarMatSeqAIJSetPreallocation
y luegoMatSetValues
para cada fila?