【发布时间】:2018-06-21 01:57:15
【问题描述】:
以下从 C++ 调用 python 函数的最小示例在我的系统上存在内存泄漏:
script.py:
import tensorflow
def foo(param):
return "something"
main.cpp:
#include "python3.5/Python.h"
#include <iostream>
#include <string>
int main()
{
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("if not hasattr(sys,'argv'): sys.argv = ['']");
PyRun_SimpleString("sys.path.append('./')");
PyObject* moduleName = PyUnicode_FromString("script");
PyObject* pModule = PyImport_Import(moduleName);
PyObject* fooFunc = PyObject_GetAttrString(pModule, "foo");
PyObject* param = PyUnicode_FromString("dummy");
PyObject* args = PyTuple_Pack(1, param);
PyObject* result = PyObject_CallObject(fooFunc, args);
Py_CLEAR(result);
Py_CLEAR(args);
Py_CLEAR(param);
Py_CLEAR(fooFunc);
Py_CLEAR(pModule);
Py_CLEAR(moduleName);
Py_Finalize();
}
编译
g++ -std=c++11 main.cpp $(python3-config --cflags) $(python3-config --ldflags) -o main
并使用 valgrind 运行
valgrind --leak-check=yes ./main
生成以下摘要
LEAK SUMMARY:
==24155== definitely lost: 161,840 bytes in 103 blocks
==24155== indirectly lost: 33 bytes in 2 blocks
==24155== possibly lost: 184,791 bytes in 132 blocks
==24155== still reachable: 14,067,324 bytes in 130,118 blocks
==24155== of which reachable via heuristic:
==24155== stdstring : 2,273,096 bytes in 43,865 blocks
==24155== suppressed: 0 bytes in 0 blocks
我正在使用Linux Mint 18.2 Sonya、g++ 5.4.0、Python 3.5.2 和 TensorFlow 1.4.1。
删除import tensorflow 会使泄漏消失。这是 TensorFlow 中的错误还是我做错了什么? (我希望后者是真的。)
另外,当我在 Python 中创建 Keras 层时
#script.py
from keras.layers import Input
def foo(param):
a = Input(shape=(32,))
return "str"
并重复从 C++ 运行对 Python 的调用
//main.cpp
#include "python3.5/Python.h"
#include <iostream>
#include <string>
int main()
{
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("if not hasattr(sys,'argv'): sys.argv = ['']");
PyRun_SimpleString("sys.path.append('./')");
PyObject* moduleName = PyUnicode_FromString("script");
PyObject* pModule = PyImport_Import(moduleName);
for (int i = 0; i < 10000000; ++i)
{
std::cout << i << std::endl;
PyObject* fooFunc = PyObject_GetAttrString(pModule, "foo");
PyObject* param = PyUnicode_FromString("dummy");
PyObject* args = PyTuple_Pack(1, param);
PyObject* result = PyObject_CallObject(fooFunc, args);
Py_CLEAR(result);
Py_CLEAR(args);
Py_CLEAR(param);
Py_CLEAR(fooFunc);
}
Py_CLEAR(pModule);
Py_CLEAR(moduleName);
Py_Finalize();
}
应用程序的内存消耗在运行期间不断增长。
所以我想我从 C++ 调用 python 函数的方式存在根本性的问题,但它是什么?
【问题讨论】:
-
您可以使用 --trace-origin=yes 查看泄漏内存的分配位置。 python 模块中通常有全局变量,它们在加载时会被初始化并且永远存在——但这不是一个大问题,因为每个模块只加载一次。
-
你的第二次内存泄漏是陌生的,也许keras有泄漏?如果未导入 keras 或未创建 Input,您是否看到内存泄漏?
-
@ead 只有在我创建
Input时才会出现循环中不断增长的 memleak。导入 Keras 只会导致第一个示例的内存泄漏。 -
@ead 内存泄漏跟踪始终显示来源。 --trace-origin 用于未初始化的内存。引用手册“要查看有关程序中未初始化数据来源的信息,请使用 --track-origins=yes 选项。这会使 Memcheck 运行得更慢,但可以更容易追踪未初始化数据的根本原因价值错误。”来自valgrind.org/docs/manual/mc-manual.html
标签: python c++ python-3.x tensorflow memory-leaks