PySide/Cython和GIL多线程使用

3

我已经花了几天时间处理一个使用PySide/Cython多线程应用程序的问题。
将问题分解成部分后,我遇到了一个我用valgrind/helgrind运行的测试(请参见下面的一个错误条目)。
C函数(下面的CHLone load)使用带有GIL的Python(没有Cython指令), Shiboken也访问GIL。
输出表明存在与GIL访问冲突的问题(除非我错了),但我的理解是GIL在那里以避免这种冲突。

Shiboken执行一些dealloc,与另一个线程上的PyList_New发生冲突...

我迷失了方向,
我认为GIL负责阻止PyList_New,同时另一个线程正在修改一些Python共享数据。或者Shiboken忘记锁定了吗?

listobject.c第161行是调用_PyObject_GC_TRACK(),该函数(我假设)要求GC跟踪新对象。
classobject.c第2360行是调用_PyObject_GC_UNTRACK(),它强烈地看起来像是要求GC停止跟踪对象...
我看到helgrind诊断是可能的数据竞争,但事实上,这会导致核心转储,我不喜欢在使用线程时在Python GC上看到可能的字眼。我首先想修复这个问题。

==26535== ----------------------------------------------------------------
==26535== 
==26535== Possible data race during read of size 8 at 0x4FE8488 by thread #2
==26535== Locks held: none
==26535==    at 0x4C92A80: PyList_New (listobject.c:161)
==26535==    by 0x742C43F: s2p_parseAndReadHDF (SIDStoPython.c:949)
==26535==    by 0x742C5C4: s2p_parseAndReadHDF (SIDStoPython.c:968)
==26535==    by 0x742E638: s2p_loadAsHDF (SIDStoPython.c:1485)
==26535==    by 0x741C3CC: __pyx_f_6CHLone_load (pyCHLone.c:2182)
==26535==    by 0x741D2AD: __pyx_pf_6CHLone_12load (pyCHLone.c:2422)
==26535==    by 0x741D1C3: __pyx_pw_6CHLone_13load (pyCHLone.c:2392)
==26535==    by 0x4D0A48F: PyEval_EvalFrameEx (ceval.c:4013)
==26535==    by 0x4D0C3DC: PyEval_EvalCodeEx (ceval.c:3253)
==26535==    by 0x4C8B641: function_call (funcobject.c:526)
==26535==    by 0x4C5F652: PyObject_Call (abstract.c:2529)
==26535==    by 0x4C7279E: instancemethod_call (classobject.c:2578)
==26535== 
==26535== This conflicts with a previous write of size 8 by thread #1
==26535== Locks held: none
==26535==    at 0x4C6C53F: instancemethod_dealloc (classobject.c:2360)
==26535==    by 0x5AB248A: Shiboken::AutoDecRef::~AutoDecRef() (in /tmp/tools-2/local/x86z/lib/python2.7/site-packages/PySide/QtCore.so)
==26535==    by 0x5F9736F: PySide::GlobalReceiverV2::qt_metacall(QMetaObject::Call, int, void**) (in /tmp/tools-2/local/x86z/lib/libpyside-python2.7.so.1.0.9)
==26535==    by 0x659BCA5: QObject::event(QEvent*) (in /tmp/tools-2/local/x86z/lib/libQtCore.so.4.8.0)
==26535==    by 0x5B038C5: QCoreApplicationWrapper::notify(QObject*, QEvent*) (in /tmp/tools-2/local/x86z/lib/python2.7/site-packages/PySide/QtCore.so)
==26535==    by 0x6586F8B: QCoreApplication::notifyInternal(QObject*, QEvent*) (in /tmp/tools-2/local/x86z/lib/libQtCore.so.4.8.0)
==26535==    by 0x658A5A7: QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (in /tmp/tools-2/local/x86z/lib/libQtCore.so.4.8.0)
==26535==    by 0x65B60F2: ??? (in /tmp/tools-2/local/x86z/lib/libQtCore.so.4.8.0)
==26535==

问题:
1. 我对GIL的行为假设是正确的吗?
2. 如果不是
... 这是否意味着我必须自己在每个线程中管理GIL锁?
... 那么我需要为Python创建自己的mutex?!??!?
3. 如果
... 在我的Cython或C库中,关于GIL使用是否存在问题?
... 这可能是QThread/QMutex的副作用吗?

1个回答

2
在CPython中,全局解释器锁(GIL)是一个互斥锁,防止多个本地线程同时执行Python字节码。因此,你只能期望GIL保持两个Python代码流不会同时执行。除此之外,你不应该期望任何形式的锁定行为。编写依赖于GIL保护的代码通常是不好的做法。GIL是许多人想要消除的瑕疵,在某些形式的Python(如IronPython和jython)中不存在。在存在时,它会降低并发性,增加开销,并使Python代码比原本更难理解。
从上述内容中我无法确定是否涉及到GIL故障。第二个跟踪似乎深入了C++领域,而不是我所了解的GIL限制范围。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接