Python threading improvements

This is a brief announcement of how VTK has recently changed for Python threading.

In the VTK master branch, the Python wrappers have been improved so that the Python GIL (global interpreter lock) is released during calls to Update(), Render(), and Write(). What this means is that, if you use Python threading in your programs, your Python threads will be able to run concurrently with VTK’s pipeline updates and rendering.

The following is a simple example that runs multiple VTK updates in multiple threads, showing modest performance improvement compared to a simple for() loop without threading: TestThreadConcurrency.py

The biggest benefit of releasing the GIL, however, is that it means that you can use Python threads to keep VTK from temporarily blocking your applications. For example, if you are loading a large file into VTK, you can spawn a new thread to call the Update() on the reader. This essentially makes the I/O asynchronous, since the VTK reader will now only block its own thread.

The release of the GIL is controlled by a new hint for the wrappers, VTK_UNBLOCKTHREADS, which is applied to the VTK Update() methods and similar methods.

4 Likes

Dear David,
Are there examples like this but for C++ codes? We have a GUI application built on top of VTK and there are rather long VTK updates that lock up the UI thread. Are there examples somewhere that show how to safely push off some of the VTK updates onto another thread so that the GUI thread is not locked up? This is using VTK 9.3.1 and Qt6 > 6.5

Thank You.

Hi Michael,

In C++ it can be done with QThread. I have no examples, because the Qt/C++ apps that I work on are not open-source, but a rough outline is as follows:

First, derive a new thread class from QThread:

class MyUpdateThread : public QThread
{
  Q_OBJECT
public:
  // constructor
  MyUpdateThread(vtkAlgorithm* alg, QObject* parent = nullptr);
  // destructor
  ~MyUpdateThread();
protected:
  // called when thread is started
  void run() override;
private:
  // the algorithm provided in the constructor
  vtkAlgorithm* m_Algorithm;
};

The run() method of this class should call the Update():

void MyUpdateThread::run()
{
  m_Algorithm->Update();
}

Then your code starts the thread with myThread->start() and checks it with myThread->isFinished(), or waits for it with myThread->wait(). Ideally the thread should also implement the abort() method for when the thread must be shut down early.