File: parallel_refcounting_stress_test.pyx

package info (click to toggle)
cython 3.0.11%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 19,092 kB
  • sloc: python: 83,539; ansic: 18,831; cpp: 1,402; xml: 1,031; javascript: 511; makefile: 403; sh: 204; sed: 11
file content (68 lines) | stat: -rw-r--r-- 1,939 bytes parent folder | download
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
# mode: run
# tag: openmp

from cython.parallel cimport prange
cimport cython
from random import randint, random

include "../buffers/mockbuffers.pxi"

# This test is designed to pick up concurrency errors in memoryview reference counting.
# It won't be 100% reliable, but hopefully does enough memoryview reference counting in
# parallel that we should see errors if it isn't thread-safe.
# It has been verified to crash if the atomic reference counting is replaced with non-atomic counting.

@cython.boundscheck(False)
@cython.wraparound(False)
def refcounting_stress_test(int N):
    """
    >>> _ = refcounting_stress_test(5000)
    acquired a
    acquired b
    acquired c
    released a
    released b
    released c
    """
    selectors = [ randint(0, 3) for _ in range(N) ]
    cdef int[::1] selectorsview = IntMockBuffer(None, selectors, (N,))
    shape = (10, 3)
    size = shape[0]*shape[1]
    a = [ random() for _ in range(size) ]
    b = [ random() for _ in range(size) ]
    c = [ random() for _ in range(size) ]
    cdef double[:,:] aview = DoubleMockBuffer("a", a, shape)
    cdef double[:,:] bview = DoubleMockBuffer("b", b, shape)
    cdef double[:,:] cview = DoubleMockBuffer("c", c, shape)

    cdef int i
    cdef double total = 0.0

    for i in prange(N, nogil=True):
        total += loopbody(aview, bview, cview, selectorsview[i])

    # make "release" order predictable
    del aview
    del bview
    del cview

    return total

@cython.boundscheck(False)
@cython.wraparound(False)
cdef double loopbody(double[:,:] a, double[:,:] b, double[:,:] c, int selector) nogil:
    cdef double[:,:] selected
    cdef double[:] subslice
    cdef double res = 0

    if selector % 3 == 1:
        selected = a
    elif selector % 3 == 2:
        selected = b
    else:
        selected = c

    for i in range(selected.shape[0]):
        subslice = selected[i, :]
        res += subslice[0] + subslice[2]
    return res