Skip to content

Commit 555d35f

Browse files
committed
Add threading tests for shared input
1 parent 5c90b69 commit 555d35f

4 files changed

Lines changed: 45 additions & 2 deletions

File tree

pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,7 @@ addopts = "--strict-markers --strict-config -v -r sxfE --color=yes --durations=1
6363
python_files = ["test_*.py"]
6464
testpaths = ["tests"]
6565
filterwarnings = ["error"]
66+
markers = [
67+
# Needed when pytest-run-parallel is not installed
68+
"thread_unsafe: Run test in single thread in pytest-run-parallel"
69+
]

tests/blis_tests_common.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Copyright ExplosionAI GmbH, released under BSD.
2+
from concurrent.futures import ThreadPoolExecutor
23
from hypothesis import settings
34
from hypothesis import strategies as st
45
from hypothesis.extra.numpy import arrays
@@ -23,3 +24,12 @@ def ndarrays(shape, lo, hi, dtype):
2324
width = int(dtype[5:])
2425
elements = st.floats(min_value=lo, max_value=hi, width=width)
2526
return arrays(dtype, shape=shape, elements=elements)
27+
28+
29+
def run_threaded(func, max_workers=8, outer_iterations=2):
30+
"""Runs a function many times in parallel"""
31+
with ThreadPoolExecutor(max_workers=max_workers) as tpe:
32+
for _ in range(outer_iterations):
33+
futures = [tpe.submit(func) for _ in range(max_workers)]
34+
for f in futures:
35+
f.result()

tests/test_dotv.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from hypothesis import strategies as st
66
from numpy.testing import assert_allclose
77

8-
from blis_tests_common import dtypes_tols, ndarrays
8+
from blis_tests_common import dtypes_tols, ndarrays, run_threaded
99
from blis.py import dotv
1010

1111

@@ -29,3 +29,17 @@ def test_memoryview_noconj(arrays):
2929
numpy_result = A.dot(B)
3030
result = dotv(A, B)
3131
assert_allclose(result, numpy_result, atol=atol, rtol=rtol)
32+
33+
34+
@given(dotv_arrays())
35+
@pytest.mark.thread_unsafe(reason="Uses run_threaded")
36+
def test_threads_share_input(arrays):
37+
"""Test when multiple threads share the same input arrays."""
38+
A, B, atol, rtol = arrays
39+
numpy_result = A.dot(B)
40+
41+
def f():
42+
result = dotv(A, B)
43+
assert_allclose(result, numpy_result, atol=atol, rtol=rtol)
44+
45+
run_threaded(f)

tests/test_gemm.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from hypothesis import strategies as st
66
from numpy.testing import assert_allclose
77

8-
from blis_tests_common import dtypes_tols, ndarrays
8+
from blis_tests_common import dtypes_tols, ndarrays, run_threaded
99
from blis.py import gemm
1010

1111

@@ -40,3 +40,18 @@ def test_memoryview_notrans(arrays):
4040
C = np.zeros_like(numpy_result) # (l, n)
4141
gemm(A, B, out=C)
4242
assert_allclose(C, numpy_result, atol=atol, rtol=rtol)
43+
44+
45+
@given(gemm_arrays())
46+
@pytest.mark.thread_unsafe(reason="Uses run_threaded")
47+
def test_threads_share_input(arrays):
48+
"""Test when multiple threads share the same input arrays."""
49+
A, B, atol, rtol = arrays
50+
numpy_result = A.dot(B)
51+
52+
def f():
53+
C = np.zeros_like(numpy_result) # (l, n)
54+
gemm(A, B, out=C)
55+
assert_allclose(C, numpy_result, atol=atol, rtol=rtol)
56+
57+
run_threaded(f)

0 commit comments

Comments
 (0)