我怎样才能防止这种内存泄漏?
How can I prevent this memory leak?
下面是我遇到的与使用 C++ 中的 Python 解释器相关的内存管理问题的简化版本。
下面的代码将 运行 正确,但它的内存占用会随着时间的推移逐渐增加。我添加了一行来手动调用 Python 垃圾收集;这并没有解决问题。
我需要用这段代码更改什么以防止不断增长的内存泄漏?
[编辑]:根据下面的建议,我进一步削减了 pythonTest 函数。它所做的只是创建一个环境,重置它,然后关闭它。内存泄漏仍然存在。
我在 Windows 10 上使用 Python 3.10.2。C++ 正在由 Visual Studio 编译为 C++14 标准。我安装了 OpenAI-Gym 版本 0.22.0。
void pythonTest(PyObject* inModule)
{
// Section 1: Get the make function:
PyObject* pMakeFunc = PyObject_GetAttrString(inModule, "make");
PyObject* pMakeArgs = PyTuple_New(1);
PyTuple_SetItem(pMakeArgs, 0, PyUnicode_FromString("LunarLanderContinuous-v2"));
// Section 2: Get the environment and its functions:
PyObject* pEnv = PyObject_CallObject(pMakeFunc, pMakeArgs);
PyObject* pEnvReset = PyObject_GetAttrString(pEnv, "reset");
PyObject* pEnvStep = PyObject_GetAttrString(pEnv, "step");
PyObject* pEnvClose = PyObject_GetAttrString(pEnv, "close");
PyObject* pEnvRender = PyObject_GetAttrString(pEnv, "render");
// Section 3: Reset the environment to get the initial observation:
PyObject* pInitialObsArray = PyObject_CallNoArgs(pEnvReset);
PyObject* pInitialObsListFunc = PyObject_GetAttrString(pInitialObsArray, "tolist");
PyObject* pInitialObsList = PyObject_CallNoArgs(pInitialObsListFunc);
// Clear section 3:
Py_CLEAR(pInitialObsList);
Py_CLEAR(pInitialObsListFunc);
Py_CLEAR(pInitialObsArray);
// Clear section 2: Close the environment, first:
PyObject_CallNoArgs(pEnvClose);
Py_CLEAR(pEnvRender);
Py_CLEAR(pEnvClose);
Py_CLEAR(pEnvStep);
Py_CLEAR(pEnvReset);
Py_CLEAR(pEnv);
// Clear section 1:
Py_CLEAR(pMakeArgs);
Py_CLEAR(pMakeFunc);
}
int main()
{
Py_Initialize();
// Get gym module:
PyObject* pGymName = PyUnicode_FromString("gym");
PyObject* pModule = PyImport_Import(pGymName);
// Get garbage collection module and collect function:
PyObject* pgcName = PyUnicode_FromString("gc");
PyObject* pgcModule = PyImport_Import(pgcName);
PyObject* pgcFunction = PyObject_GetAttrString(pgcModule, "collect");
for (int k = 0; k < 1000000; ++k)
{
pythonTest(pModule);
// Manually invoke the garbage collection:
PyObject* pGCReturn = PyObject_CallNoArgs(pgcFunction);
auto objectsCollected = PyLong_AsLong(pGCReturn);
std::cout << "Iteration " << k << " objects collected: "
<< objectsCollected << std::endl;
Py_CLEAR(pGCReturn);
}
Py_CLEAR(pgcFunction);
Py_CLEAR(pgcModule);
Py_CLEAR(pgcName);
Py_CLEAR(pModule);
Py_CLEAR(pGymName);
Py_Finalize();
return 0;
}
您每次循环都在创建一个新的 pActionList,但您似乎没有处理它。
一般来说,虽然您将此描述为代码的精简版本,但它仍然相当复杂。我会说继续剥离它直到问题消失。那应该告诉你问题出在哪里。
问题既不在 Python 也不在它的 C++ 接口中。问题出在一些 OpenAI Gym 环境使用的 Box2D 中。
我可以重复上面的代码,同时创建一个不使用 Box2D 的不同环境(例如“CartPole-v1”)并让它 运行 无休止地没有任何内存泄漏。一旦我放回 Box2D 环境(例如“BipedalWalker-v3”或“LunarLander-v2”),内存泄漏又回来了。
我可以在 Python 中完全重复上述过程并得到相同的结果。即使在每次环境破坏后手动 运行ning 垃圾收集,应用程序分配的内存也会无限增长。
任何环境中的重置函数都是为 运行 做大量准备的地方,也是发生内存泄漏的地方。如果无休止地创建和销毁 Box2D 环境,则不会发生内存泄漏。创建,重置,然后销毁?内存泄漏。
谢谢大家的帮助,但这是底层库中的一个错误。我需要去那里提交。
下面是我遇到的与使用 C++ 中的 Python 解释器相关的内存管理问题的简化版本。
下面的代码将 运行 正确,但它的内存占用会随着时间的推移逐渐增加。我添加了一行来手动调用 Python 垃圾收集;这并没有解决问题。
我需要用这段代码更改什么以防止不断增长的内存泄漏?
[编辑]:根据下面的建议,我进一步削减了 pythonTest 函数。它所做的只是创建一个环境,重置它,然后关闭它。内存泄漏仍然存在。
我在 Windows 10 上使用 Python 3.10.2。C++ 正在由 Visual Studio 编译为 C++14 标准。我安装了 OpenAI-Gym 版本 0.22.0。
void pythonTest(PyObject* inModule)
{
// Section 1: Get the make function:
PyObject* pMakeFunc = PyObject_GetAttrString(inModule, "make");
PyObject* pMakeArgs = PyTuple_New(1);
PyTuple_SetItem(pMakeArgs, 0, PyUnicode_FromString("LunarLanderContinuous-v2"));
// Section 2: Get the environment and its functions:
PyObject* pEnv = PyObject_CallObject(pMakeFunc, pMakeArgs);
PyObject* pEnvReset = PyObject_GetAttrString(pEnv, "reset");
PyObject* pEnvStep = PyObject_GetAttrString(pEnv, "step");
PyObject* pEnvClose = PyObject_GetAttrString(pEnv, "close");
PyObject* pEnvRender = PyObject_GetAttrString(pEnv, "render");
// Section 3: Reset the environment to get the initial observation:
PyObject* pInitialObsArray = PyObject_CallNoArgs(pEnvReset);
PyObject* pInitialObsListFunc = PyObject_GetAttrString(pInitialObsArray, "tolist");
PyObject* pInitialObsList = PyObject_CallNoArgs(pInitialObsListFunc);
// Clear section 3:
Py_CLEAR(pInitialObsList);
Py_CLEAR(pInitialObsListFunc);
Py_CLEAR(pInitialObsArray);
// Clear section 2: Close the environment, first:
PyObject_CallNoArgs(pEnvClose);
Py_CLEAR(pEnvRender);
Py_CLEAR(pEnvClose);
Py_CLEAR(pEnvStep);
Py_CLEAR(pEnvReset);
Py_CLEAR(pEnv);
// Clear section 1:
Py_CLEAR(pMakeArgs);
Py_CLEAR(pMakeFunc);
}
int main()
{
Py_Initialize();
// Get gym module:
PyObject* pGymName = PyUnicode_FromString("gym");
PyObject* pModule = PyImport_Import(pGymName);
// Get garbage collection module and collect function:
PyObject* pgcName = PyUnicode_FromString("gc");
PyObject* pgcModule = PyImport_Import(pgcName);
PyObject* pgcFunction = PyObject_GetAttrString(pgcModule, "collect");
for (int k = 0; k < 1000000; ++k)
{
pythonTest(pModule);
// Manually invoke the garbage collection:
PyObject* pGCReturn = PyObject_CallNoArgs(pgcFunction);
auto objectsCollected = PyLong_AsLong(pGCReturn);
std::cout << "Iteration " << k << " objects collected: "
<< objectsCollected << std::endl;
Py_CLEAR(pGCReturn);
}
Py_CLEAR(pgcFunction);
Py_CLEAR(pgcModule);
Py_CLEAR(pgcName);
Py_CLEAR(pModule);
Py_CLEAR(pGymName);
Py_Finalize();
return 0;
}
您每次循环都在创建一个新的 pActionList,但您似乎没有处理它。
一般来说,虽然您将此描述为代码的精简版本,但它仍然相当复杂。我会说继续剥离它直到问题消失。那应该告诉你问题出在哪里。
问题既不在 Python 也不在它的 C++ 接口中。问题出在一些 OpenAI Gym 环境使用的 Box2D 中。
我可以重复上面的代码,同时创建一个不使用 Box2D 的不同环境(例如“CartPole-v1”)并让它 运行 无休止地没有任何内存泄漏。一旦我放回 Box2D 环境(例如“BipedalWalker-v3”或“LunarLander-v2”),内存泄漏又回来了。
我可以在 Python 中完全重复上述过程并得到相同的结果。即使在每次环境破坏后手动 运行ning 垃圾收集,应用程序分配的内存也会无限增长。
任何环境中的重置函数都是为 运行 做大量准备的地方,也是发生内存泄漏的地方。如果无休止地创建和销毁 Box2D 环境,则不会发生内存泄漏。创建,重置,然后销毁?内存泄漏。
谢谢大家的帮助,但这是底层库中的一个错误。我需要去那里提交。