Потоковая программа C на языке OpenMP останавливается при вызове скрипта Python (используя matplotlib) в параллельной области - PullRequest
1 голос
/ 28 марта 2019

У меня есть многопоточная программа на C, использующая OpenMP. Внутри параллельного раздела кода для системного вызова делается скрипт Python, который отображает данные, сгенерированные в этой конкретной итерации цикла. У меня есть проблема, когда программа внезапно останавливается в той же точке после тысяч итераций и часов работы. После запуска ps -A, чтобы увидеть, какие процессы выполнялись в стойле, я заметил n-много экземпляров python (где n = количество потоков), что привело меня к мысли, что что-то происходит со скриптом python. Я переключился с системного вызова на сценарий python на встроенный python, надеясь, что это решит проблему. Теперь я вижу, что запуск сценария python выдает предупреждение:

OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.

Я не использую ничего, связанного с BLAS, в моем коде, но после проб и ошибок я обнаружил, что это производится matplotlib, который зависит от numpy, который, в свою очередь, я полагаю, использует OpenBLAS. Я подозреваю, что это может быть виновником возможного срыва, но я не уверен, как это исправить. Я попытался установить OpenBLAS со страницы GitHub и сделать это с флагом USE_OPENMP=1, как показано здесь:

Как заставить openBLAS работать с openMP?

Это, я полагаю, неудивительно, не решило проблему. Я подозреваю, что мне придется переделать любой источник BLAS, который использует matplotlib? В любом случае я привел минимальный пример, который воспроизводит нежелательное поведение. Код OpenMP C находится здесь:

#include <sys/wait.h>
#include <python2.7/Python.h>
#include "omp.h"

int NUM_THREADS = 8;        // Default number of threads for OpenMP

int main(int argc, char * argv[])
{
   # ifdef _OPENMP
   printf("Compiled by an OpenMP-compliant implementation.\n");
   # endif

   omp_set_dynamic(0);
   omp_set_num_threads(NUM_THREADS);

   int nThreads = 0;

   #pragma omp parallel
   {

   #pragma omp master
   nThreads = omp_get_num_threads();

   #pragma omp for
   for (int i = 0; i < 8; i++)  // Loop through number of samples
   {
     // Create directories to store and run the python script
     char system_buffer[300] = "\0";
     snprintf(system_buffer, sizeof(system_buffer), "mkdir -p %d", i+1);
     int systemRet = system(system_buffer);
     if(systemRet == -1)
     {
       // The system method failed
     }

     // Copy the Python Script to the working directory
     char system_buffer_py[300] = "\0";
     snprintf(system_buffer_py, sizeof(system_buffer_py), "cp test.py %d", i+1);
     int systemRet_py = system(system_buffer_py);
     if(systemRet_py == -1)
     {
       // The system method failed
     }

     int pid;

     // Child
     if ((pid = fork()) == 0)
     {
       int argc = 0;
       char* argv[1];
       argv[0] = NULL;

       char python_script[300] = "\0";
       snprintf(python_script, sizeof(python_script), "%d/test.py", i+1);

       FILE *stream = fopen(python_script, "r");

       Py_SetProgramName(argv[0]);
       Py_Initialize();
       PySys_SetArgv(argc, argv);
       PyRun_AnyFile(stream, python_script);
       Py_Finalize();

       fclose(stream);

       exit(0);
     } 
     // Parent
     else
     {
       int status;
       waitpid(pid, &status, 0);
     }
   }

   }//end of: pragma omp parallel

   if  (nThreads == NUM_THREADS) 
   {
     printf("The expected number of threads, %d, were used.\n", NUM_THREADS);
   }
   else 
   {
     printf("Expected %d OpenMP threads, but %d were used.\n", NUM_THREADS, nThreads);
   }

   return(0);
}

Это можно скомпилировать с помощью:

gcc -Wall -O3 -fopenmp test.c -o test -L/usr/lib/python2.7/config-x86_64-linux-gnu -L/usr/lib -lpython2.7 -ldl -export-dynamic -lm

Сценарий python находится здесь и должен находиться в том же каталоге, что и код C:

import os
import matplotlib.pyplot as plt

plot_name = os.path.dirname(__file__) + '/test.png'

plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.savefig(plot_name)

Выход от запуска кода C:

Compiled by an OpenMP-compliant implementation.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
OpenBLAS Warning : Detect OpenMP Loop and this application may hang. Please rebuild the library with USE_OPENMP=1 option.
The expected number of threads, 8, were used.

Похоже, это предупреждение генерируется 3 раза для каждого потока (используя 8 потоков). Будем весьма благодарны за любые предложения по решению этой проблемы.

1 Ответ

0 голосов
/ 02 апреля 2019

Зная, что ссылка не может быть ответом, но так как я никогда не пытался смешивать потоки и fork (). Эта статья может помочь.

...