Skip to content

Conversation

digikar99
Copy link
Owner

Fixes #11

This PR adds the variables py4cl2-cffi/config:*python-call-mode* and py4cl2-cffi:+python-call-mode+, along with appropriate changes to ecase on these variables.

The central idea is that when python call mode is :single-threaded, py4cl2-cffi starts the python interpreter in its own separate thread. All calls to python via pyvalue pycall and friends occur through this thread. This allows libraries like matplotlib to assume that there is a single thread.

To use this functionality -

(asdf:load-system "py4cl2-cffi/config")
(setf py4cl2-cffi/config:*python-call-mode* :single-threaded) ; or :multi-threaded - this is the default
(asdf:load-system "py4cl2-cffi" :force t)
(py4cl2-cffi:pystart)

Note that the decision to use a separate thread or otherwise needs to be made before python initialization aka pystart.

This also makes the single-threaded/ directory unnecessary.

Two main concerns with this PR include:

  1. Naming: :dedicated and :standard instead of :single-threaded and :multi-threaded sound more informative. I'd be happy to hear any opinions from repository watchers or anyone passing by.
  2. :single-threaded mode is about 10 times slower than :multi-threaded. I'm also yet to benchmark :multi-threaded against the existing code. Ideally, this should not incur a penalty, since we are trying to push the decisions to compile time instead of runtime.

@digikar99
Copy link
Owner Author

Running the scripts in ./perf-compare/ indicates a minimal loss of performance with the :multi-threaded mode above. Though, the :single-threaded mode is unimaginably slower. Comparing against (funcall/single-threaded #'identity i) in a loop reveals :single-threaded can be upto 10 times faster without modifying the current thread synchronization primitives.

@digikar99
Copy link
Owner Author

Proof of concept: Wrapping the body of pycall inside with-dedicated-python-thread committed in 0c69d4d boosts the performance in :single-threaded mode by about 5 times(!)

@digikar99 digikar99 force-pushed the python-call-mode branch 3 times, most recently from dd3a17f to e18dd82 Compare May 23, 2025 09:20
@atzmueller
Copy link
Contributor

I think :dedicated and :standard are OK.

@digikar99
Copy link
Owner Author

With the way calls are made to the dedicated thread via dedicated-thread-utils.lisp, there's not much performance to be gained beyond what 5ce8660 enables.

PY4CL2-CFFI> (time
              (loop for i below 10000 do (funcall/dedicated-thread #'pycall "str" i)))
  0.253 seconds of real time
NIL
PY4CL2-CFFI> (time
              (loop for i below 10000 do (funcall/dedicated-thread #'null i)))
  0.232 seconds of real time
NIL
PY4CL2-CFFI> (time
              (loop for i below 10000 do (funcall/dedicated-thread #'null-pointer)))
  0.189 seconds of real time
NIL

This is 10+ time slower than when *python-call-mode* is :standard.

I think this PR is ready to be merged. Perhaps in the future, if someone discovers a better method of sync-ing or interthread calls, this might be optimizable.

@digikar99 digikar99 merged commit 1e85e17 into master Jun 28, 2025
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

plt.plot hangs
2 participants