Fdtd3d: Dúvidas em computação paralela

Criado em 8 jan. 2020  ·  9Comentários  ·  Fonte: zer011b/fdtd3d

Olá Gleb,

Eu sou Chengyi. Obrigado por desenvolver este magnífico projeto. É realmente útil para estudar FDTD e sua simultaneidade. Mas encontrei alguns problemas ao usar a computação MPI/GPU.

  1. O problema é que quando chamo o código fdtd3d usando o seguinte comando,
    ./Release/Source/fdtd3d --cmd-from-file ./Examples/vacuum3D_test.txt
    em que criei "vacuum3D_test.txt" com base no "vacuum3D.txt" inserindo o seguinte código
--use-cuda
--cuda-buffer-size 1
--cuda-gpus 0
--num-cuda-threads-x 4
--num-cuda-threads-y 4
--num-cuda-threads-z 4

o programa mostrará apenas o log "Carregando linha de comando do arquivo ./Examples/vacuum3D_test.txt
" e continue esperando até eu matá-lo. Eu só estou querendo saber se há algumas configurações que eu não configurei corretamente?
A propósito, este é o meu cmake flags caso você precise:
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVALUE_TYPE=f -DPRINT_MESSAGE=ON -DCUDA_ENABLED=ON -DCUDA_ARCH_SM_TYPE=sm_60 -DCXX11_ENABLED=ON -DPARALLEL_GRID=ON -DPARALLEL_GRID_DIMENSION=3

  1. Além disso, quando simulei o "vacuum3D.txt" pelo MPI, a escalabilidade apresentada pelo fdtd3d não é muito ideal. Por exemplo, o tamanho da grade é 40 por 40 por 40, o que equivale a 64.000. E eu tenho um chip que tem 18 núcleos. Quando for com 1 processo, custará 67,74 segundos e será em torno de 11,34 segundos com 8 processadores habilitados. O speedup é em torno de 6. E quando eu aplico mais processadores como 18, a redução de tempo é trivial, digamos de 11,34 s para 9,6 s. Isso é razoável? Posso perguntar se existem configurações de simulação que podem ajustar o desempenho da computação paralela?

Se você precisar de mais detalhes de simulação, por favor me avise. Muito obrigado.

Com muitos agradecimentos e votos,
Chengyi

Question

Todos 9 comentários

  1. Eu não acho que ele está travado, ele apenas executa cálculos, que são muito mais lentos mesmo no modo RelWithDebInfo . Além disso, o log completo é impresso no final da execução no caso de lançamentos do Cuda.

Pequena dica: é mais rápido (em termos de compilação e execução) especificar -DSOLVER_DIM_MODES , se você souber exatamente quais modos usará. Por padrão, todos os modos são compilados em binário, o que aumenta significativamente o tempo de compilação no caso de compilações Cuda. No seu caso -DSOLVER_DIM_MODES=DIM3 seria suficiente.

  1. Há algumas coisas para manter em mente aqui. Em primeiro lugar, o tempo total de execução de cada passo de tempo é a soma do tempo computacional e do tempo de compartilhamento. Quando a grade é relativamente pequena, como no seu caso, o tempo de compartilhamento pode ser significativo e a escolha cuidadosa da topologia virtual é necessária (fdtd3d mostra a melhor topologia virtual para o tamanho da grade especificada em sua saída).

No entanto, em sistemas com compartilhamento de memória compartilhada, as operações não são necessárias (exceto para sincronização de encadeamento). É por isso que o OpenMP é muito mais aplicável aqui do que o MPI, e os programas baseados em MPI não mostrarão a melhor aceleração. Infelizmente, o OpenMP ainda não é suportado no fdtd3d.

Com tudo isso em mente, ainda há coisas para ajustar no fdtd3d.

  • Por padrão, apenas o eixo Ox é distribuído entre os nós computacionais, mas você pode alterar isso com -DPARALLEL_BUFFER_DIMENSION=xyz , que dividirá a grade entre os pedaços em todas as dimensões. Verifique a saída fdtd3d porque ela aconselha a topologia virtual ideal.
  • O tamanho do buffer pode ser configurado com --buffer-size B , e a operação de compartilhamento será executada apenas a cada B etapas. Nesse caso, a topologia virtual ideal, que é recomendada pelo fdtd3d, não é garantida como ideal. Mas você pode definir a topologia virtual manualmente com --manual-topology --topology-sizex X --topology-sizey Y --topology-sizez Z .

Observe que quando o número de processos não é um divisor do tamanho geral da grade, a topologia virtual ideal, aconselhada por fdtd3d, também não é garantida como ideal.

Obrigado por esta resposta oportuna.

  1. Quanto à computação de GPU única, refiz o fdtd3d com os seguintes sinalizadores

cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVALUE_TYPE=f -DPRINT_MESSAGE=ON -DCUDA_ENABLED=ON -DCXX11_ENABLED=ON -DPARALLEL_GRID=ON -DPARALLEL_GRID_DIMENSION=3 -DSOLVER_DIM_MODES=DIM3 -DPARALLEL_BUFFER_DIMENSION=x

e funcionou na minha estação de trabalho. (BTW, minha estação de trabalho tem quatro Tesla P100s, dos quais o arco deve ser SM_60)

  1. Quando eu quero habilitar a computação multi-gpu com
    mpiexec --mca btl ^openib -n 2 ./Release/Source/fdtd3d --cmd-from-file ./Examples/vacuum3D_test.txt
    e os cmds CUDA
--use-cuda
--cuda-buffer-size 2
--buffer-size 2
--cuda-gpus 0,1
--num-cuda-threads-x 4
--num-cuda-threads-y 4
--num-cuda-threads-z 4

erro ocorre como mostrado:

Calculating time step 0...
Calculating time step 1...
Fatal error: an illegal memory access was encountered at /home/t00540502/fdtd3d/Source/Scheme/InternalScheme.inc.h:912
*** FAILED - ABORTING
-------------------------------------------------------
Primary job  terminated normally, but 1 process returned
a non-zero exit code.. Per user-direction, the job has been aborted.

Parece que o primeiro passo foi bom, mas algo errado com a função InternalSchemeKernelHelpers::calculateFieldStepIterationKernel chamando no 2º passo. Eu estou querendo saber que deve haver alguns erros que cometi ao usar o MPI + CUDA. Você pode me ensinar como chamá-lo corretamente?
Muito obrigado.

Melhor

Talvez algo esteja errado com o sm_60 arch, não testei. O arco padrão é sm_20, então deve funcionar em seus cartões. No entanto, às vezes eu vi illegal memory access quando o cuda arch não correspondia à capacidade de computação da GPU.

Os cálculos multi-gpu têm aplicabilidade limitada. Se todos os dados couberem na memória de uma única GPU, será muito mais rápido realizar cálculos nessa única GPU em um único nó computacional (porque não haverá compartilhamento de dados intermediário entre CPU/GPU e entre diferentes nós computacionais).

Mas quando as grades são muito grandes e não podem ser localizadas na memória de um único nó computacional, não há escolha a não ser usar vários nós computacionais, cada um possivelmente com uma GPU. Neste caso, o compartilhamento de dados CPU-GPU e CPU-CPU será realizado a cada B etapas, por padrão B=1 . Isso é muito mais lento do que cálculos simples de todas as etapas de tempo em uma única GPU.

Os cálculos multi-gpu ainda não são totalmente suportados no fdtd3d, porque atualmente o fdtd3d depende do usuário para ter certeza de que todos os dados cabem onde devem caber (assim como no modo somente CPU). Então, com tais limitações, deve funcionar.

@solotcy Houve um bug com o arco não definido (consulte #140). Por favor, verifique com sm_60 sobre esse PR.

Illegal memory access está relacionado ao acesso à variável global cudaSolverSettings, que está localizada na memória do dispositivo (veja INTERNAL_SCHEME_BASE<Type, TCoord, layout_type>::calculateFieldStepIteration ):

if (SOLVER_SETTINGS.getDoUseTFSF ())

Em 2 de 3 GPUs com a mesma capacidade de computação sm_35, nas quais testei fdtd3d, tudo funciona bem (todas as GPUs são modelos diferentes). No entanto, em um, por algum motivo, cudaSolverSettings se torna NULL, ao inserir o método getDoUseTFSF (ou seja, este ptr é NULL). Não consegui entender por que isso acontece, mas pelo que descobri isso pode acontecer devido ao mau funcionamento do dispositivo.

Parece que você conseguiu iniciar o fdtd3d com sucesso pelo menos em uma de suas 4 GPUs. Experimente o modo somente GPU em cada GPU separadamente. Como todas as suas 4 GPUs são exatamente iguais, não deve haver nenhuma diferença no comportamento do fdtd3d. Se houver uma diferença, a causa de um mau funcionamento do dispositivo se torna mais provável.

Muito obrigado pelas respostas.

Eu verifiquei o PR #140 e reconstruí o fdtd3d com o sinalizador -DCUDA_ARCH_SM_TYPE=sm_60 adicionado. Infelizmente acontece o mesmo problema.

No entanto, como você mencionou, encontrei o mesmo erro ao alternar entre diferentes GPUs no modo de GPU única. E não é no primeiro passo, mas no segundo, como antes,

Estimated current size: 1437644553 byte.
Setup blocks:
blockCount:
Coord (X : 1.000000, Y : 1.000000, Z : 1.000000).
blockSize:
Coord (X : 200.000000, Y : 200.000000, Z : 200.000000).
Calculating time step 0...
Calculating time step 1...
Fatal error: an illegal memory access was encountered at ~/fdtd3d/Source/Scheme/InternalScheme.inc.h:912

E as coisas ficam meio estranhas, pois só funcionou na primeira GPU. Para outros três, tudo falhou e teve as mesmas informações de erro.

Obrigado por seus testes! Consegui finalmente descobrir o motivo principal desse problema. PR #141 resolve o problema. Agora o fdtd3d deve funcionar em todas as suas GPUs. O modo multi-gpu parece funcionar também agora.

Obrigado por suas respostas e pelo código modificado. Consegui executar o programa na minha estação de trabalho com quantas GPUs eu quiser. Então eu posso testar a escalabilidade em CPUs e GPUs.
É bem legal, obrigado!!!

Sinta-se à vontade para reabrir este problema se tiver mais perguntas.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

alranel picture alranel  ·  116Comentários

slothbag picture slothbag  ·  108Comentários

dictoon picture dictoon  ·  10Comentários

ultimatexemnas picture ultimatexemnas  ·  37Comentários

andersk picture andersk  ·  81Comentários