From d7399beaf63fe9e973bab8747aab9c4f25f6b228 Mon Sep 17 00:00:00 2001 From: "Todd A. Anderson" Date: Thu, 27 Aug 2026 20:04:02 -0700 Subject: [PATCH 1/9] Add NUMBA_SMART_PRIVATIZE default to true to give old behavior of only used in region to be private. If set to false then such variables become shared. --- src/numba/openmp/config.py | 1 + src/numba/openmp/omp_lower.py | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/numba/openmp/config.py b/src/numba/openmp/config.py index 84e2edc48545..42b133f3eb41 100644 --- a/src/numba/openmp/config.py +++ b/src/numba/openmp/config.py @@ -25,3 +25,4 @@ def _safe_readenv(name, ctor, default): OPENMP_DISABLED = _safe_readenv("NUMBA_OPENMP_DISABLED", int, 0) # Use toolchain for device code compilation by default to avoid issues with libomptarget compatibility checks. OPENMP_DEVICE_TOOLCHAIN = _safe_readenv("NUMBA_OPENMP_DEVICE_TOOLCHAIN", int, 1) +SMART_PRIVATIZE = _safe_readenv("NUMBA_SMART_PRIVATIZE", int, 1) diff --git a/src/numba/openmp/omp_lower.py b/src/numba/openmp/omp_lower.py index 955fe81e8d7a..d54a20a1fc25 100644 --- a/src/numba/openmp/omp_lower.py +++ b/src/numba/openmp/omp_lower.py @@ -18,7 +18,7 @@ import sys import os -from .config import DEBUG_OPENMP +from .config import DEBUG_OPENMP, SMART_PRIVATIZE from .parser import openmp_parser from .analysis import ( remove_ssa, @@ -304,7 +304,10 @@ def should_be_firstprivate(var_name): # All private variables (user-defined and compiler-generated) for var_name in sorted(private_to_region): - add_clause(var_name, "QUAL.OMP.PRIVATE") + if SMART_PRIVATIZE: + add_clause(var_name, "QUAL.OMP.PRIVATE") + else: + add_clause(var_name, "QUAL.OMP.SHARED") def make_implicit_explicit_target( self, From daf397810f473712e377ee796a93c64eeb21024e Mon Sep 17 00:00:00 2001 From: "Todd A. Anderson" Date: Wed, 2 Sep 2026 12:58:23 -0700 Subject: [PATCH 2/9] Default smart privatize to off. --- src/numba/openmp/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numba/openmp/config.py b/src/numba/openmp/config.py index 42b133f3eb41..10fc2b2357d4 100644 --- a/src/numba/openmp/config.py +++ b/src/numba/openmp/config.py @@ -25,4 +25,4 @@ def _safe_readenv(name, ctor, default): OPENMP_DISABLED = _safe_readenv("NUMBA_OPENMP_DISABLED", int, 0) # Use toolchain for device code compilation by default to avoid issues with libomptarget compatibility checks. OPENMP_DEVICE_TOOLCHAIN = _safe_readenv("NUMBA_OPENMP_DEVICE_TOOLCHAIN", int, 1) -SMART_PRIVATIZE = _safe_readenv("NUMBA_SMART_PRIVATIZE", int, 1) +SMART_PRIVATIZE = _safe_readenv("NUMBA_SMART_PRIVATIZE", int, 0) From eefad1f55e88a9ca0e092dfa1bf9bd216113d351 Mon Sep 17 00:00:00 2001 From: "Todd A. Anderson" Date: Wed, 2 Sep 2026 14:07:05 -0700 Subject: [PATCH 3/9] Mark var x as private in test_pi_loop variants. --- src/numba/openmp/tests/test_openmp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/numba/openmp/tests/test_openmp.py b/src/numba/openmp/tests/test_openmp.py index c3aee25fa37c..411ad456ee9e 100644 --- a/src/numba/openmp/tests/test_openmp.py +++ b/src/numba/openmp/tests/test_openmp.py @@ -4610,7 +4610,7 @@ def test_impl(num_steps): omp_set_num_threads(4) with openmp("parallel"): - with openmp("for reduction(+:the_sum) schedule(static)"): + with openmp("for private(x) reduction(+:the_sum) schedule(static)"): for j in range(num_steps): x = ((j - 1) - 0.5) * step the_sum += 4.0 / (1.0 + x * x) @@ -4629,7 +4629,7 @@ def test_impl(num_steps): the_sum = 0.0 omp_set_num_threads(4) - with openmp("parallel for reduction(+:the_sum) schedule(static)"): + with openmp("parallel for private(x) reduction(+:the_sum) schedule(static)"): for j in range(num_steps): x = ((j - 1) - 0.5) * step the_sum += 4.0 / (1.0 + x * x) @@ -4647,7 +4647,7 @@ def test_impl(num_steps): the_sum = 0.0 omp_set_num_threads(4) - with openmp("loop reduction(+:the_sum) schedule(static)"): + with openmp("loop private(x) reduction(+:the_sum) schedule(static)"): for j in range(num_steps): x = ((j - 1) - 0.5) * step the_sum += 4.0 / (1.0 + x * x) From a6b0a93ee4d419a3448f886393f5f4fbf57a875a Mon Sep 17 00:00:00 2001 From: "Todd A. Anderson" Date: Wed, 2 Sep 2026 14:51:31 -0700 Subject: [PATCH 4/9] Add explicit private. --- src/numba/openmp/tests/test_openmp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/numba/openmp/tests/test_openmp.py b/src/numba/openmp/tests/test_openmp.py index 411ad456ee9e..c61e815bd905 100644 --- a/src/numba/openmp/tests/test_openmp.py +++ b/src/numba/openmp/tests/test_openmp.py @@ -2050,7 +2050,7 @@ def test_impl(N, iters): with openmp("parallel"): with openmp("barrier"): pass - with openmp("for private(p, sum)"): + with openmp("for private(p, sum, i)"): for _ in range(iters): with openmp("critical"): p = count @@ -2074,7 +2074,7 @@ def test_impl(N): omp_set_num_threads(N) ca = np.zeros(N) sum = 0 - with openmp("parallel private(sum) shared(c)"): + with openmp("parallel private(sum, i) shared(c)"): c = N with openmp("barrier"): pass @@ -2117,7 +2117,7 @@ def test_impl(N): omp_set_num_threads(N) a = np.zeros((2, N)) sa = np.zeros(N) - with openmp("parallel private(a0c, sum, tn)"): + with openmp("parallel private(a0c, sum, tn, j)"): tn = omp_get_thread_num() with openmp("barrier"): pass From e3b38c71330a8bab011113354b67d5af778b7ab5 Mon Sep 17 00:00:00 2001 From: "Todd A. Anderson" Date: Sat, 26 Sep 2026 19:21:07 -0700 Subject: [PATCH 5/9] internal vars private to region become omp private. --- src/numba/openmp/omp_lower.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numba/openmp/omp_lower.py b/src/numba/openmp/omp_lower.py index d54a20a1fc25..03466131b63a 100644 --- a/src/numba/openmp/omp_lower.py +++ b/src/numba/openmp/omp_lower.py @@ -304,7 +304,7 @@ def should_be_firstprivate(var_name): # All private variables (user-defined and compiler-generated) for var_name in sorted(private_to_region): - if SMART_PRIVATIZE: + if SMART_PRIVATIZE or is_internal_var(ir.Var(scope, var_name, self.loc)): add_clause(var_name, "QUAL.OMP.PRIVATE") else: add_clause(var_name, "QUAL.OMP.SHARED") From b3d5f4a460c473992c489b863541d951a03e3c31 Mon Sep 17 00:00:00 2001 From: "Todd A. Anderson" Date: Sat, 26 Sep 2026 19:21:24 -0700 Subject: [PATCH 6/9] Missing private var i. --- src/numba/openmp/tests/test_openmp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numba/openmp/tests/test_openmp.py b/src/numba/openmp/tests/test_openmp.py index c61e815bd905..059f217b3dea 100644 --- a/src/numba/openmp/tests/test_openmp.py +++ b/src/numba/openmp/tests/test_openmp.py @@ -4670,7 +4670,7 @@ def test_impl(num_steps): omp_set_num_threads(j) full_sum = 0.0 - with openmp("parallel private(tid, numthreads, local_sum, x)"): + with openmp("parallel private(tid, numthreads, local_sum, x, i)"): tid = omp_get_thread_num() numthreads = omp_get_num_threads() local_sum = 0.0 From 2c5be6b3af3bd40d9eb5fc8ce3eeeec2d20d312f Mon Sep 17 00:00:00 2001 From: "Todd A. Anderson" Date: Tue, 29 Sep 2026 18:54:28 -0700 Subject: [PATCH 7/9] loop index add to clauses as string instead of var. --- src/numba/openmp/omp_lower.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numba/openmp/omp_lower.py b/src/numba/openmp/omp_lower.py index 03466131b63a..c6764d8f89f9 100644 --- a/src/numba/openmp/omp_lower.py +++ b/src/numba/openmp/omp_lower.py @@ -938,7 +938,7 @@ def _get_loop_kind(func_var, call_table): if latest_index.name not in vars_in_explicit_clauses: new_index_clause = openmp_tag( "QUAL.OMP.PRIVATE", - ir.Var(loop_index.scope, latest_index.name, inst.loc), + latest_index.name, ) clauses.append(new_index_clause) vars_in_explicit_clauses[latest_index.name] = new_index_clause From dd054694c29535ff6b2f63b38514dfc38274f141 Mon Sep 17 00:00:00 2001 From: "Todd A. Anderson" Date: Tue, 29 Sep 2026 19:07:54 -0700 Subject: [PATCH 8/9] Add private to test. --- src/numba/openmp/tests/test_openmp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numba/openmp/tests/test_openmp.py b/src/numba/openmp/tests/test_openmp.py index 059f217b3dea..c7d4962f8dbf 100644 --- a/src/numba/openmp/tests/test_openmp.py +++ b/src/numba/openmp/tests/test_openmp.py @@ -2371,7 +2371,7 @@ def test_task_basic(self): @njit def test_impl(ntsks): a = np.zeros(ntsks) - with openmp("parallel"): + with openmp("parallel private(i)"): with openmp("single"): for i in range(ntsks): with openmp("task"): From d24ec33a11394b615826bef3699b15b40001ec79 Mon Sep 17 00:00:00 2001 From: "Todd A. Anderson" Date: Tue, 29 Sep 2026 19:50:38 -0700 Subject: [PATCH 9/9] Make deconstruct vars internal. --- src/numba/openmp/omp_lower.py | 6 +++--- src/numba/openmp/tests/test_openmp.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/numba/openmp/omp_lower.py b/src/numba/openmp/omp_lower.py index c6764d8f89f9..bfca1eaecf3b 100644 --- a/src/numba/openmp/omp_lower.py +++ b/src/numba/openmp/omp_lower.py @@ -652,7 +652,7 @@ def get_loops_in_region(all_loops): ) deconstruct_indices = [] - new_deconstruct_var = new_var_scope.redefine("deconstruct", self.loc) + new_deconstruct_var = new_var_scope.redefine("$deconstruct", self.loc) deconstruct_indices.append( ir.Assign(loop_bounds[-1][1], new_deconstruct_var, self.loc) ) @@ -668,7 +668,7 @@ def get_loops_in_region(all_loops): operator.floordiv, new_deconstruct_var, cur_iterspace_var, self.loc ) new_deconstruct_var_loop = new_var_scope.redefine( - "deconstruct" + str(deconstruct_index), self.loc + "$deconstruct" + str(deconstruct_index), self.loc ) deconstruct_indices.append( ir.Assign(deconstruct_div, cur_loop_bound, self.loc) @@ -676,7 +676,7 @@ def get_loops_in_region(all_loops): # if DEBUG_OPENMP >= 1: # deconstruct_indices.append(ir.Print([cur_loop_bound], None, self.loc)) new_deconstruct_var_mul = new_var_scope.redefine( - "deconstruct_mul" + str(deconstruct_index), self.loc + "$deconstruct_mul" + str(deconstruct_index), self.loc ) deconstruct_indices.append( ir.Assign( diff --git a/src/numba/openmp/tests/test_openmp.py b/src/numba/openmp/tests/test_openmp.py index c7d4962f8dbf..93366e8e04ff 100644 --- a/src/numba/openmp/tests/test_openmp.py +++ b/src/numba/openmp/tests/test_openmp.py @@ -4477,8 +4477,8 @@ def test_impl(n): b = np.ones((n, n)) c = np.zeros((n, n)) with openmp(target_pragma): - with openmp("teams"): - with openmp("loop collapse(2)"): + with openmp("teams private(i,j)"): + with openmp("loop collapse(2) private(i,j)"): for i in range(n): for j in range(n): c[i, j] = a[i, j] + b[i, j]