1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
# mode: run
# tag: openmp
cimport cython
cimport cython.parallel
cdef cython.pymutex global_lock
cdef void hide_the_reduction(int *x) noexcept nogil:
x[0] = x[0] + 1
def global_lock_with_prange():
"""
>>> global_lock_with_prange()
5000
"""
cdef int count = 0
cdef int i
for i in cython.parallel.prange(5000, nogil=True):
with global_lock:
hide_the_reduction(&count)
return count
def local_lock_with_prange():
"""
>>> local_lock_with_prange()
5000
"""
cdef int count = 0
cdef int i
cdef cython.pymutex lock
for i in cython.parallel.prange(5000, nogil=True):
with lock:
hide_the_reduction(&count)
return count
cdef class HasLockAttribute:
cdef cython.pymutex lock
def lock_on_attribute(HasLockAttribute has_lock):
"""
>>> lock_on_attribute(HasLockAttribute())
5000
"""
cdef int count = 0
cdef int i
for i in cython.parallel.prange(5000, nogil=True):
with has_lock.lock:
hide_the_reduction(&count)
return count
def lock_in_closure():
"""
>>> lock_in_closure()
5000
"""
cdef int count = 0
cdef int i
# pythread_type_lock and pymutex should behave basically the same. So test them both
cdef cython.pythread_type_lock lock
def inner():
with lock:
hide_the_reduction(&count)
for i in cython.parallel.prange(5000, nogil=True):
with gil:
inner()
return count
def manual_acquire_release():
"""
>>> manual_acquire_release()
5000
"""
cdef int count = 0
cdef int i
cdef cython.pymutex lock
for i in cython.parallel.prange(5000, nogil=True):
# Test it both with and without the GIL
if i % 2 == 0:
with gil:
lock.acquire()
hide_the_reduction(&count)
lock.release()
else:
lock.acquire()
hide_the_reduction(&count)
lock.release()
return count
# Although forbidden to pass a copy of the lock, pointers are fine
cdef void acquire_and_hide(cython.pymutex* l, int* i) nogil noexcept:
with l[0]:
hide_the_reduction(i)
def pass_as_pointer():
"""
>>> pass_as_pointer()
5000
"""
cdef int count = 0
cdef int i
cdef cython.pymutex lock
for i in cython.parallel.prange(5000, nogil=True):
acquire_and_hide(&lock, &count)
return count
|