【问题标题】:Calling a Python function in loop from C++ runs slow after hours从 C++ 循环调用 Python 函数数小时后运行缓慢
【发布时间】:2021-12-19 21:36:00
【问题描述】:

我在 for 循环中从 C++ 调用 Python 函数时遇到了麻烦。 C++ 程序制作图片,Python 脚本将其转换为调整大小的 jpeg 图像。

来自 C++ 的调用的 sn-p:

char *antwort;                              
// Python
PyObject *fname, *module, *pFunc, *pArgs, *pValue;
Py_Initialize();
PyObject* fname = PyUnicode_FromString((char*)"TEST");
PyObject* module = PyImport_Import(fname);
printf("OK -> ");
pFunc = PyObject_GetAttrString(module, (char*)"umwandeln");
pArgs = PyTuple_Pack(1, PyUnicode_FromString((char*)filename));
pValue = PyObject_CallObject(pFunc, pArgs);
auto result = _PyUnicode_AsString(pValue);


antwort = result;                           
Py_DECREF(pFunc);
Py_DECREF(module);
Py_DECREF(fname);
Py_DECREF(pArgs);
Py_DECREF(
Py_Finalize();

Python 脚本:

import sys
import os
import gc
from PIL import Image

def umwandeln(filenam):
    Test = str(filenam)
    Test = Test[2:]
    print ("file : " + Test)
    if Test[-3:] == "tif" or Test[-3:] == "bmp" :
       # print "is tif or bmp"
       outfile = Test[:-3] + "jpeg"
       im = Image.open(Test)
       print ("new filename : " + outfile)
       out = im.convert("RGB")

            
       out.save(outfile, "JPEG", quality=95)
       im.close()
      # print(outfile)
       im2 = Image.open(outfile)
       im2 = im2.resize((300,300),Image.ANTIALIAS)
       im2.save(outfile)
       im2.close()


       os.remove(Test)
       print ("Fertig Script")  
       gc.collect()
       
    
    return outfile

Python 文件的名称是 Test.py。 它可以运行大约 3-4 小时(它不会突然逐渐变慢)。然后我认为PyImport_Import() 运行缓慢。

如果我再次启动 cpp 程序,它会正常运行,但一段时间后会越来越慢。

内存使用量大约是大小的一半(从 8 到 3GB)。 CPU 使用率约为 30%。

有什么想法吗?

【问题讨论】:

  • 为什么每次都要杀掉Python环境?为什么不在两次跑步之间保持它呢?看起来您对 Python 脚本的界面是“这是一个文件名,变魔术并给我一个新文件名”。为什么不直接运行python script.py filename filename.out

标签: python c++ linux


【解决方案1】:

这听起来像是随着时间的推移内存碎片的问题。你一直在同一个进程中运行,在每个 python 调用中创建/销毁至少 5 个对象(更不用说你在 umwandeln() 中调用的 python 函数中可能更高的数字)。

您可以尝试将 umwandeln() 中的一些变量设为静态,这样就不需要在每次调用时都分配/释放它们。

另一种方法是将 umwandeln() 函数分解为单独的 python 脚本,添加文件名作为脚本参数。然后,您可以直接从 C++ 或使用 python 子进程模块 (https://docs.python.org/3/library/subprocess.html) 调用脚本,就好像它是一个外部程序(它是)一样。这样做还意味着您可以通过为不同的文件名多次调用外部脚本来并行调整图像大小。

这是我用于图像预处理/后处理的方法之一,我可以高兴地报告说,我在 24 核 (Threadripper) Linux PC 上的负载因子已达到 250 以上,它会吐出像这样的图像没有明天。

/否

【讨论】:

    猜你喜欢
    • 2012-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 2018-11-27
    • 2019-03-25
    相关资源
    最近更新 更多