summaryrefslogtreecommitdiff
path: root/docs/examples/tutorial/parallelization
diff options
context:
space:
mode:
Diffstat (limited to 'docs/examples/tutorial/parallelization')
-rw-r--r--docs/examples/tutorial/parallelization/manual_work.py24
-rw-r--r--docs/examples/tutorial/parallelization/manual_work.pyx25
-rw-r--r--docs/examples/tutorial/parallelization/median.py35
-rw-r--r--docs/examples/tutorial/parallelization/median.pyx34
-rw-r--r--docs/examples/tutorial/parallelization/norm.py12
-rw-r--r--docs/examples/tutorial/parallelization/norm.pyx12
-rw-r--r--docs/examples/tutorial/parallelization/normalize.py16
-rw-r--r--docs/examples/tutorial/parallelization/normalize.pyx17
-rw-r--r--docs/examples/tutorial/parallelization/parallel_sin.py16
-rw-r--r--docs/examples/tutorial/parallelization/parallel_sin.pyx16
-rw-r--r--docs/examples/tutorial/parallelization/setup.py29
11 files changed, 236 insertions, 0 deletions
diff --git a/docs/examples/tutorial/parallelization/manual_work.py b/docs/examples/tutorial/parallelization/manual_work.py
new file mode 100644
index 000000000..d6b0167d9
--- /dev/null
+++ b/docs/examples/tutorial/parallelization/manual_work.py
@@ -0,0 +1,24 @@
+# tag: openmp
+
+from cython.parallel import parallel
+from cython.cimports.openmp import omp_get_thread_num
+import cython
+
+@cython.cfunc
+@cython.nogil
+def long_running_task1() -> cython.void:
+ pass
+
+@cython.cfunc
+@cython.nogil
+def long_running_task2() -> cython.void:
+ pass
+
+def do_two_tasks():
+ thread_num: cython.int
+ with cython.nogil, parallel(num_threads=2):
+ thread_num = omp_get_thread_num()
+ if thread_num == 0:
+ long_running_task1()
+ elif thread_num == 1:
+ long_running_task2()
diff --git a/docs/examples/tutorial/parallelization/manual_work.pyx b/docs/examples/tutorial/parallelization/manual_work.pyx
new file mode 100644
index 000000000..886015839
--- /dev/null
+++ b/docs/examples/tutorial/parallelization/manual_work.pyx
@@ -0,0 +1,25 @@
+# tag: openmp
+
+from cython.parallel cimport parallel
+from openmp cimport omp_get_thread_num
+
+
+
+
+cdef void long_running_task1() nogil:
+ pass
+
+
+
+cdef void long_running_task2() nogil:
+ pass
+
+def do_two_tasks():
+ cdef int thread_num
+ with nogil, parallel(num_threads=2):
+ thread_num = omp_get_thread_num()
+ if thread_num == 0:
+ long_running_task1()
+ elif thread_num == 1:
+ long_running_task2()
+
diff --git a/docs/examples/tutorial/parallelization/median.py b/docs/examples/tutorial/parallelization/median.py
new file mode 100644
index 000000000..535a2b136
--- /dev/null
+++ b/docs/examples/tutorial/parallelization/median.py
@@ -0,0 +1,35 @@
+# distutils: language = c++
+
+from cython.parallel import parallel, prange
+from cython.cimports.libc.stdlib import malloc, free
+from cython.cimports.libcpp.algorithm import nth_element
+import cython
+from cython.operator import dereference
+
+import numpy as np
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def median_along_axis0(x: cython.double[:,:]):
+ out: cython.double[::1] = np.empty(x.shape[1])
+ i: cython.Py_ssize_t
+ j: cython.Py_ssize_t
+ scratch: cython.pointer(cython.double)
+ median_it: cython.pointer(cython.double)
+ with cython.nogil, parallel():
+ # allocate scratch space per loop
+ scratch = cython.cast(
+ cython.pointer(cython.double),
+ malloc(cython.sizeof(cython.double)*x.shape[0]))
+ try:
+ for i in prange(x.shape[1]):
+ # copy row into scratch space
+ for j in range(x.shape[0]):
+ scratch[j] = x[j, i]
+ median_it = scratch + x.shape[0]//2
+ nth_element(scratch, median_it, scratch + x.shape[0])
+ # for the sake of a simple example, don't handle even lengths...
+ out[i] = dereference(median_it)
+ finally:
+ free(scratch)
+ return np.asarray(out)
diff --git a/docs/examples/tutorial/parallelization/median.pyx b/docs/examples/tutorial/parallelization/median.pyx
new file mode 100644
index 000000000..242cb6091
--- /dev/null
+++ b/docs/examples/tutorial/parallelization/median.pyx
@@ -0,0 +1,34 @@
+# distutils: language = c++
+
+from cython.parallel cimport parallel, prange
+from libcpp.vector cimport vector
+from libcpp.algorithm cimport nth_element
+cimport cython
+from cython.operator cimport dereference
+
+import numpy as np
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def median_along_axis0(const double[:,:] x):
+ cdef double[::1] out = np.empty(x.shape[1])
+ cdef Py_ssize_t i, j
+
+ cdef vector[double] *scratch
+ cdef vector[double].iterator median_it
+ with nogil, parallel():
+ # allocate scratch space per loop
+ scratch = new vector[double](x.shape[0])
+ try:
+ for i in prange(x.shape[1]):
+ # copy row into scratch space
+ for j in range(x.shape[0]):
+ dereference(scratch)[j] = x[j, i]
+ median_it = scratch.begin() + scratch.size()//2
+ nth_element(scratch.begin(), median_it, scratch.end())
+ # for the sake of a simple example, don't handle even lengths...
+ out[i] = dereference(median_it)
+ finally:
+ del scratch
+ return np.asarray(out)
+
diff --git a/docs/examples/tutorial/parallelization/norm.py b/docs/examples/tutorial/parallelization/norm.py
new file mode 100644
index 000000000..1d8c2758a
--- /dev/null
+++ b/docs/examples/tutorial/parallelization/norm.py
@@ -0,0 +1,12 @@
+from cython.parallel import prange
+import cython
+from cython.cimports.libc.math import sqrt
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def l2norm(x: cython.double[:]):
+ total: cython.double = 0
+ i: cython.Py_ssize_t
+ for i in prange(x.shape[0], nogil=True):
+ total += x[i]*x[i]
+ return sqrt(total)
diff --git a/docs/examples/tutorial/parallelization/norm.pyx b/docs/examples/tutorial/parallelization/norm.pyx
new file mode 100644
index 000000000..5a702f975
--- /dev/null
+++ b/docs/examples/tutorial/parallelization/norm.pyx
@@ -0,0 +1,12 @@
+from cython.parallel cimport prange
+cimport cython
+from libc.math cimport sqrt
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def l2norm(double[:] x):
+ cdef double total = 0
+ cdef Py_ssize_t i
+ for i in prange(x.shape[0], nogil=True):
+ total += x[i]*x[i]
+ return sqrt(total)
diff --git a/docs/examples/tutorial/parallelization/normalize.py b/docs/examples/tutorial/parallelization/normalize.py
new file mode 100644
index 000000000..0519be4d4
--- /dev/null
+++ b/docs/examples/tutorial/parallelization/normalize.py
@@ -0,0 +1,16 @@
+from cython.parallel import parallel, prange
+import cython
+from cython.cimports.libc.math import sqrt
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def normalize(x: cython.double[:]):
+ i: cython.Py_ssize_t
+ total: cython.double = 0
+ norm: cython.double
+ with cython.nogil, parallel():
+ for i in prange(x.shape[0]):
+ total += x[i]*x[i]
+ norm = sqrt(total)
+ for i in prange(x.shape[0]):
+ x[i] /= norm
diff --git a/docs/examples/tutorial/parallelization/normalize.pyx b/docs/examples/tutorial/parallelization/normalize.pyx
new file mode 100644
index 000000000..e167ad7ad
--- /dev/null
+++ b/docs/examples/tutorial/parallelization/normalize.pyx
@@ -0,0 +1,17 @@
+from cython.parallel cimport parallel, prange
+cimport cython
+from libc.math cimport sqrt
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def normalize(double[:] x):
+ cdef Py_ssize_t i
+ cdef double total = 0
+ cdef double norm
+ with nogil, parallel():
+ for i in prange(x.shape[0]):
+ total += x[i]*x[i]
+ norm = sqrt(total)
+ for i in prange(x.shape[0]):
+ x[i] /= norm
+
diff --git a/docs/examples/tutorial/parallelization/parallel_sin.py b/docs/examples/tutorial/parallelization/parallel_sin.py
new file mode 100644
index 000000000..be6cbc030
--- /dev/null
+++ b/docs/examples/tutorial/parallelization/parallel_sin.py
@@ -0,0 +1,16 @@
+from cython.parallel import prange
+import cython
+from cython.cimports.libc.math import sin
+
+import numpy as np
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def do_sine(input: cython.double[:,:]):
+ output : cython.double[:,:] = np.empty_like(input)
+ i : cython.Py_ssize_t
+ j : cython.Py_ssize_t
+ for i in prange(input.shape[0], nogil=True):
+ for j in range(input.shape[1]):
+ output[i, j] = sin(input[i, j])
+ return np.asarray(output)
diff --git a/docs/examples/tutorial/parallelization/parallel_sin.pyx b/docs/examples/tutorial/parallelization/parallel_sin.pyx
new file mode 100644
index 000000000..c3091541e
--- /dev/null
+++ b/docs/examples/tutorial/parallelization/parallel_sin.pyx
@@ -0,0 +1,16 @@
+from cython.parallel cimport prange
+cimport cython
+from libc.math cimport sin
+
+import numpy as np
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def do_sine(double[:,:] input):
+ cdef double[:,:] output = np.empty_like(input)
+ cdef Py_ssize_t i, j
+
+ for i in prange(input.shape[0], nogil=True):
+ for j in range(input.shape[1]):
+ output[i, j] = sin(input[i, j])
+ return np.asarray(output)
diff --git a/docs/examples/tutorial/parallelization/setup.py b/docs/examples/tutorial/parallelization/setup.py
new file mode 100644
index 000000000..eb343e5da
--- /dev/null
+++ b/docs/examples/tutorial/parallelization/setup.py
@@ -0,0 +1,29 @@
+from setuptools import Extension, setup
+from Cython.Build import cythonize
+import sys
+
+if sys.platform.startswith("win"):
+ openmp_arg = '/openmp'
+else:
+ openmp_arg = '-fopenmp'
+
+
+ext_modules = [
+ Extension(
+ "*",
+ ["*.pyx"],
+ extra_compile_args=[openmp_arg],
+ extra_link_args=[openmp_arg],
+ ),
+ Extension(
+ "*",
+ ["*.pyx"],
+ extra_compile_args=[openmp_arg],
+ extra_link_args=[openmp_arg],
+ )
+]
+
+setup(
+ name='parallel-tutorial',
+ ext_modules=cythonize(ext_modules),
+)