Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #177 #180

Merged
merged 4 commits into from
Oct 31, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 67 additions & 17 deletions ImageD11/cImageD11.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@


# import cImageD11 compiled module and patch the docstrings

import sys
import struct
import warnings
from ImageD11 import cImageD11_docstrings

try:
Expand All @@ -19,43 +17,95 @@
print(" python setup.py build_ext --inplace")
raise

# Check for the use of openmp interactions with os.fork and multiprocessing

def check_multiprocessing():
""" You cannot safely use os.fork together with threads.
But the cImageD11 codes uses threads via openmp.
So please use forkserver or spawn for multiprocessing.

https://discuss.python.org/t/concerns-regarding-deprecation-of-fork-with-alive-threads/33555
https://github.com/FABLE-3DXRD/ImageD11/issues/177

> Developers should respond by adjusting their use of multiprocessing or concurrent.futures
> to explicitly specify either the "forkserver" or "spawn" start methods via a context.
"""
import multiprocessing
# Problem cases are:
# child processes -> we will set num threads to 1
parent = None
if hasattr(multiprocessing,"parent_process"):
parent = multiprocessing.parent_process()
# only for python 3.8 and up
cimaged11_omp_set_num_threads( 1 )
# people wanting Nprocs * Mthreads need to reset after import
# OMP_NUM_THREADS is not going to work for them
# how are we going to remember this in the future??
#
# now check for the fork issue
if ((multiprocessing.get_start_method(allow_none=False) == 'fork') and # we have the problem
(multiprocessing.get_start_method(allow_none=True) is None) and # by accident
('forkserver' in multiprocessing.get_all_start_methods())): # so fix it
multiprocessing.set_start_method('forkserver')
if ((multiprocessing.get_start_method(allow_none=False) == 'fork') and # we have the problem
(parent is not None)):
# Tell them about it.
warnings.warn(__doc__)



if cimaged11_omp_get_max_threads() == 0:
# The code was compiled without openmp
OPENMP = False
else:
# Openmp threading can be used
OPENMP = True
check_multiprocessing()


# For 32 or 64 bits
nbyte = struct.calcsize("P") # 4 or 8
nbyte = struct.calcsize("P") # 4 or 8

if nbyte == 8:
def put_incr(*a,**k):
""" redirects to put_incr64 """
return put_incr64(*a,**k)

def put_incr(*a, **k):
"""redirects to put_incr64"""
return put_incr64(*a, **k)


if nbyte == 4:
def put_incr(*a,**k):
""" redirects to put_incr32 """
return put_incr32(*a,**k)

def put_incr(*a, **k):
"""redirects to put_incr32"""
return put_incr32(*a, **k)


# Add / fix the docstrings

def fix_doc( oldstring, to_be_added ):
""" Adds a description of the function to the f2py string """

def fix_doc(oldstring, to_be_added):
"""Adds a description of the function to the f2py string"""
if oldstring.find("Wrapper for"):
try:
head, tail = oldstring.split("Wrapper for")
except:
print( oldstring )
print( to_be_added )
print(oldstring)
print(to_be_added)
raise
iname = tail.find("\n")
return head + tail[:iname] + " " + to_be_added + tail[iname:]
else:
return oldstring + to_be_added


def fill_in_docstrings():
for name in cImageD11_docstrings.__all__:
doc = getattr( cImageD11_docstrings, name )
doc = getattr(cImageD11_docstrings, name)
if name in globals():
func = globals()[name]
func.__doc__ = fix_doc( func.__doc__, doc )
func.__doc__ = fix_doc(func.__doc__, doc)


fill_in_docstrings()

assert verify_rounding(20) == 0, "Problem with cImageD11 fast rounding code"