Qual é a maneira mais eficiente de obter uma matriz esparsa complexa do meu código Fortran para o PETSc? Entendo que isso depende do problema, então tentei fornecer o maior número possível de detalhes relevantes abaixo.
Eu estou brincando com o solucionador de autovalor FEAST [1] para problemas do tipo , a dimensão das matrizes e é , e praticamente todo o tempo gasto resolvendo sistema linear complexo com o lado direito M0. N é grande (número de funções básicas da FE, em 3D), M0 é pequeno (no meu caso, estou interessado em M0 ~ 20). As matrizes e são reais, simétricas e esparsas, e o problema complexo que precisa ser resolvido é , ondeé um número complexo. O autor do FEAST parece sugerir que a precisão da solução para esse sistema linear não precisa ser muito alta para obter valores próprios e vetores próprios precisos, portanto alguns solucionadores iterativos rápidos podem ser uma ótima solução para isso.
Até agora, eu apenas uso o Lapack para o sistema complexo, e isso funciona muito bem para no meu computador. Para maior , ainda não sei qual é o melhor solucionador, então eu queria apenas usar o PETSc e brincar com os solucionadores iterativos lá.
Eu escrevi um driver C simples, e chamo-o de Fortran, veja [2] para todo o código, mas o problema é apenas com essa parte (atualização: coloquei aqui todas as linhas para criar a matriz, como acabei de perceber que isso é 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);
O que é extremamente lento (ou seja, para N ~ 1500, isso leva talvez 2s, enquanto a resolução é imediata); na verdade, a MatSetValues
linha leva praticamente 100% de todo o tempo para todo o cálculo do autovalor ... A matriz A_ é uma Matriz 2D que vem do Fortran. Eu tentei desativar o MAT_IGNORE_ZERO_ENTRIES
mas não fez nenhuma diferença. Então, acho que o problema simplesmente é que, mesmo para N moderado como 1500, preciso usar algum formato de matriz esparsa, está correto?
Portanto, implementei o formato CSR no meu código Fortran para as matrizes e (ou para o ) e agora estou tentando descobrir como fornecê-lo ao PETSc de forma eficiente. Por enquanto, eu só quero que algo funcione sequencialmente, que supera Lapack. Devo usar a função para isso?MatCreateSeqAIJWithArrays
Essa é a maneira mais eficiente de fazer isso? Como as matrizes e não mudam, apenas o número complexo muda no algoritmo FEAST e, em um cálculo de FE, acho que ambos e têm a mesma estrutura esparsa, provavelmente é possível melhorar ainda mais as coisas pré-alocando o estrutura esparsa e, em seguida, apenas avalie rapidamente em cada iteração FEAST (o , são as matrizes de valores do formato CSR), posso fazer isso facilmente no Fortran, mas talvez seja lento sempre chamar , portanto, pode ser mais rápido para fazer tudo isso no PETSc uma vez que as matrizes eMatCreateSeqAIJWithArrays
são transferidos.
Gostaria de saber se essa abordagem de RSE para esse problema está correta ou se estou fazendo errado (claramente minha abordagem original com a opção MatSetValues
não é ótima). Obrigado por todas as dicas.
[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
fonte
MatSetValues()
. Para traduzir uma matriz existente, não é mais rápido chamar apenasMatCreateSeqAIJWithArrays
uma vez, em vez de chamarMatSeqAIJSetPreallocation
e depoisMatSetValues
para cada linha?MatSetValues()
será muito pequeno em comparação com o cálculo das entradas e a solução do sistema. Além disso, a montagem usandoMatSetValues[Blocked][Local]()
evita que seu código dependa de um formato de matriz específico, permitindo escolher formatos de armazenamento em tempo de execução.