OpenMP 线程化 C 程序在并行区域中调用 python 脚本(使用 matplotlib)时会停止



>我有一个使用 OpenMP 进行多线程处理的 C 程序。在代码的并行 for 部分中,对 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,而 numpy 反过来,我收集,使用 OpenBLAS。我怀疑这可能是最终停滞背后的罪魁祸首,但我不确定如何解决它。我尝试从GitHub页面安装OpenBLAS,并使用USE_OPENMP=1标志进行安装,如下所述:

如何使openBLAS与openMP一起工作?

我想这并不奇怪,并没有解决问题。我怀疑我将不得不重新制作 matplotlib 正在使用的任何 BLAS 来源?无论如何,我提供了一个最小的例子来重现不良行为。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] = "";
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] = "";
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] = "";
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.

因此,似乎每个线程(使用 8 个线程)抛出此警告 3 次。如能就解决这一问题提供任何意见,将不胜感激。

知道链接不可能是答案,但是因为我从未尝试过混合线程和fork()。 这篇文章可能会有所帮助。

最新更新