Почему `total_num_virtual_procs` не равен количеству процессов MPI?

#python #nest-simulator

#python #гнездо-симулятор

Вопрос:

В симуляторе NEST есть концепция виртуальных процессов. Читая информацию о виртуальных процессах, я бы ожидал, что каждый процесс MPI будет содержать как минимум 1 виртуальный процесс, иначе этот процесс MPI ничего не делает?

Однако, когда я запускаю 4 процесса MPI, атрибут состояния ядра total_num_virtual_procs является 1 :

 mpiexec -n 4 python -c "import nest; import mpi4py.MPI; print(nest.GetKernelStatus()['total_num_virtual_procs'], mpi4py.MPI.COMM_WORLD.Get_size());"
  

Это печатает текст импорта гнезда и 1 4 четыре раза. Означает ли это, что 3 процесса не будут использоваться для моделирования, пока я не сделаю nest.SetKernelStatus({'total_num_virtual_procs': 4}) ?

Ответ №1:

РЕДАКТИРОВАТЬ: TL; DR: Возвращаемое значение nest.GetKernelStatus('total_num_virtual_procs') было ошибочным в предыдущих версиях NEST. Последние версии показывают правильное число, которое по умолчанию равно одному потоку на процесс, поэтому количество процессов MPI.

Количество виртуальных процессов является свободным параметром NEST, потому что он использует гибридную схему распараллеливания с MPI OpenMP. У вас может быть несколько потоков на процесс, каждый из которых является собственным виртуальным процессом, например, два процесса и четыре VPS приводят к двум потокам на процесс:

 Process  Thread  VP
-------  ------  --
0        0       0
1        0       1
0        1       2
1        1       3
  

Установка total_num_virtual_procs на восемь приведет к созданию четырех потоков на процесс и так далее. Приведенный выше пример работает даже без mpi4py подобного:

 mpiexec -n 2 python -c "
   import nest; 
   nest.SetKernelStatus({'total_num_virtual_procs': 4}); 
   print('>>> this is process %d of %d with %d threads <<<' 
         % ( nest.Rank(),
             nest.NumProcesses(), 
             nest.GetKernelStatus()['total_num_virtual_procs']/nest.NumProcesses()) 
   ); 
   nest.Simulate(10);"
  

Среди выходных данных есть следующие строки:

>>> this is process 1 of 2 with 2 threads <<<
>>> this is process 0 of 2 with 2 threads <<<
…

Sep 09 15:49:39 SimulationManager::start_updating_ [Info]: 
    Number of local nodes: 0
    Simulation time (ms): 10
    Number of OpenMP threads: 2
    Number of MPI processes: 2

Sep 09 15:49:39 SimulationManager::start_updating_ [Info]: 
    Number of local nodes: 0
    Simulation time (ms): 10
    Number of OpenMP threads: 2
    Number of MPI processes: 2
  

Вы можете видеть, что total_num_virtual_procs разделяется по всем процессам, так что Number of OpenMP threads времена Number of MPI processes равны total_num_virtual_procs . Далее вы отмечаете, что вы не видите здесь распараллеливания потоков на уровне Python, поскольку процессы вводят параллельный контекст только в Create() , Connect() и Simulate() вызовах в области C ниже.

  • Если вы не установили, total_num_virtual_procs по умолчанию используется один поток на процесс. Вы можете увидеть это, просто создав несколько нейронов nest.Create('iaf_psc_exp', 10) , например, в двух процессах:

     Sep 09 16:28:28 SimulationManager::start_updating_ [Info]: 
        Number of local nodes: 5
        Number of local nodes: 5
        Simulation time (ms): 10
        Simulation time (ms): 10
        Number of OpenMP threads: 1
        Number of OpenMP threads: 1
        Number of MPI processes: 2
        Number of MPI processes: 2
      

    Каждый процесс обрабатывает пять из десяти созданных нейронов. ( nest.GetKernelStatus('total_num_virtual_procs') тогда должно быть возвращено количество процессов. Какую версию NEST вы используете? Это уже было исправлено …)

  • Если количество VPS, которое вы хотите установить, не кратно числу вложенных процессов MPI, генерируется исключение.

      nest.lib.hl_api_exceptions.BadProperty: ('BadProperty in SetKernelStatus: Number of virtual processes (threads*processes) must be an integer multiple of the number of processes. Value unchanged.', 'BadProperty', 'SetKernelStatus', ': Number of virtual processes (threads*processes) must be an integer multiple of the number of processes. Value unchanged.')`
      

Обычно хорошей отправной точкой при экспериментировании с различными геометриями ваших заданий является один процесс MPI на домен NUMA (например, один процесс на физический сокет процессора) и один поток на физическое ядро (гиперпоточность может вызвать борьбу за строки кэша, что может даже снизить производительность).

Комментарии:

1. О, так это может быть потому, что я использую NEST 2.18! Может быть, вы могли бы добавить это в начало своего ответа для ясности 🙂