
    J/Ph                        d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZmZmZmZ ddlmZmZmZmZmZmZ ddlZddlmZ ddlm Z  edz
  Z!	 ddl"m#Z#  e#             dd	l$m%Z% d
Z&n# e'$ r dZ&Y nw xY w	 ddl$m(Z( d
Z)n# e'$ r dZ)Y nw xY w	 ddl*Z+d
Z,n# e'$ r dZ,Y nw xY w ej-        e)d          Z. ej-        e&d          Z/e)o
e(j0        dk    Z1 ej-        e1d          Z2ej3        4                    d          Z5ej3        4                    d          Z6ej7        dk    Z8e8Z9e5 Z:d Z;e,rd Z<nd Z<d Z=d Z> G d de?          Z@ G d de@          ZA G d de?          ZB G d d e@          ZC G d! d"e@          ZD G d# d$e@          ZEd% ZFd& ZGe
jH        ZI G d' d(e?          ZJd) ZK eGeIejL                  ZM eG eKd*           ZNe5s eG eKd+           ZO eG eKd,           ZP eG eKd-           ZQ G d. d/e          ZRe jS        d0v ZT ej-        eTd1           G d2 d3eR                      ZUeUV                                  G d4 d5e?          ZW G d6 d7eWeR          ZXeXV                                  G d8 d9e          ZYe G d: d;eY                      ZZeZV                                 e G d< d=eY                      Z[e G d> d?eY                      Z\ee2 G d@ dAeY                                  Z]ee/ G dB dCeY                                  Z^e G dD dEe                      Z_ee. G dF dGe                                  Z`eadHk    r ejb                     dS dS )Iz
Tests the parallel backend
    N)jit	vectorizeguvectorizeset_num_threads)temp_directoryoverride_configTestCasetagskip_parfors_unsupported
linux_only)_TIMEOUT)configg      N@)_check_tbb_version_compatible)tbbpoolTF)omppoolzOpenMP threadpool requiredzTBB threadpool requiredGNUzGNU OpenMP only testswindarwinl        c                 0    t          j        |           |z   S N)nponesnvs     a/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/numba/tests/test_parallel_backend.pyfoor   H   s    71::>    c                     t          j        t          j        | | f          t          j        | | f                    }|t          j        |           z   |z   S r   )r   dotr   arange)r   r   xs      r   linalgr#   M   sC    F27Aq6??BGQFOO4429Q<<!##r   c                 0    t          j        |           |z   S r   )r   r!   r   s     r   r#   r#   Q   s    y||ar   c                     | |z   S r    )abs     r   	ufunc_foor)   V   s    q5Lr   c                     | |z   |d<   d S )Nr   r&   )r'   r(   outs      r   
gufunc_foor,   Z   s    UCFFFr   c                       e Zd Zd ZdS )runnablec                     || _         d S r   )_options)selfoptionss     r   __init__zrunnable.__init___   s    r   N)__name__
__module____qualname__r3   r&   r   r   r.   r.   ^   s#                 r   r.   c                       e Zd Zd ZdS )
jit_runnerc                      t          di | j        t                    }d}d}t          ||          } |||          }t          j                            ||           d S N   
   r&   )r   r0   r   r   testingassert_allcloser1   cfuncr'   r(   expectedgots         r   __call__zjit_runner.__call__e   se    $$$dm$$S))q!99eAqkk

""8S11111r   Nr4   r5   r6   rC   r&   r   r   r8   r8   c   #        2 2 2 2 2r   r8   c                       e Zd Zd Zd ZdS )mask_runnerc                 "    || _         || _        d S r   )runnermask)r1   rI   rJ   r2   s       r   r3   zmask_runner.__init__o   s    			r   c                 d    | j         rt          | j                    |                                  d S r   )rJ   r   rI   )r1   s    r   rC   zmask_runner.__call__s   s/    9 	' DI&&&r   Nr4   r5   r6   r3   rC   r&   r   r   rG   rG   n   s2              r   rG   c                       e Zd Zd ZdS )linalg_runnerc                      t          di | j        t                    }d}d}t          ||          } |||          }t          j                            ||           d S r:   )r   r0   r#   r   r=   r>   r?   s         r   rC   zlinalg_runner.__call__}   se    $$$dm$$V,,!Q<<eAqkk

""8S11111r   NrD   r&   r   r   rN   rN   {   rE   r   rN   c                       e Zd Zd ZdS )vectorize_runnerc                 <    t          dgfi | j        t                    }t          j                            d                              t          j                  x}}t          ||          } |||          }t          j                            ||           d S )Nz(f4, f4)r<   )	r   r0   r)   r   randomastypefloat32r=   r>   r?   s         r   rC   zvectorize_runner.__call__   s    8	:,88$-88CC	  $$++BJ777AQ??eAqkk

""8S11111r   NrD   r&   r   r   rQ   rQ      s#        2 2 2 2 2r   rQ   c                       e Zd Zd ZdS )guvectorize_runnerc                 B   dg} t          |dfi | j        t                    }t          j                            d                              t          j                  x}}t          ||          } |||          }t          j        	                    ||           d S )Nz(f4, f4, f4[:])z	(),()->()r<   )
r   r0   r,   r   rS   rT   rU   r)   r=   r>   )r1   sigr@   r'   r(   rA   rB   s          r   rC   zguvectorize_runner.__call__   s     !>C>>>>zJJ	  $$++BJ777AQ??eAqkk

""8S11111r   NrD   r&   r   r   rW   rW      rE   r   rW   c                 L   |                     d          }	 t          j                     t          t	          t          |           dz                      D ] }t          j        |           } |             !d S # t          $ r }|	                    |           Y d }~d S d }~ww xY w)Nqueueg      ?)
getfaulthandlerenablerangeintlenrS   choice	Exceptionput)fnlistkwargsq_fnes         r   chooserrk      s    

7As3v;;,--.. 	 	Av&&BBDDDD	 	    	as   A A9 9
B#BB#c                       fd}|S )Nc                                  }d|i fdt          d          D             }|D ]}|                                 |D ]}|                                 |                                sg }|                                s<|                    |                    d                     |                                <d}t          |d                    d |D                       z            d S )Nr[   c                 8    g | ]} t           f           S ))targetargsrf   )rk   ).0ire   kwsparallel_classs     r   
<listcomp>z8compile_factory.<locals>.run_compile.<locals>.<listcomp>   s<     " " " ~WF9SIII " " "r   r;   Fz)Error(s) occurred in delegated runner:
%s
c                 ,    g | ]}t          |          S r&   )repr)rq   r"   s     r   ru   z8compile_factory.<locals>.run_compile.<locals>.<listcomp>   s    0I0I0IQa0I0I0Ir   )r_   startjoinemptyappendr\   RuntimeError)	re   rg   thstherrors_msgrs   rt   
queue_impls	   `     @r   run_compilez$compile_factory.<locals>.run_compile   s    JLLl" " " " " "a" " " 	 	BHHJJJJ 	 	BGGIIIIwwyy 	LFggii ,aeeEll+++ ggii ,?Dtdii0I0I&0I0I0I&J&JJKKK	L 	Lr   r&   )rt   r   r   s   `` r   compile_factoryr      s0    L L L L L L r   c                       e Zd Zd Zd ZdS )_proc_class_implc                     || _         d S r   )_method)r1   methods     r   r3   z_proc_class_impl.__init__   s    r   c                 N    t          j        | j                  } |j        |i |S r   )multiprocessingget_contextr   Process)r1   rp   rf   ctxs       r   rC   z_proc_class_impl.__call__   s+    )$,77s{D+F+++r   NrL   r&   r   r   r   r      s2          , , , , ,r   r   c                 n    | dk    rd } t          j        |           }t          |           }|j        }||fS )Ndefault)r   r   r   Queue)r   r   procr[   s       r   _get_mp_classesr      s@    

%f
-
-CF##DIE;r   spawnfork
forkserverr   c                      e Zd ZdZ ed           edd           edd           ed           edd           ed           edd           eddd           ed           edd           eddd          gZe	sI edd	           eddd
           edd	           eddd
          gZ
e                    e
           ej        dk     rg ZnddgZg ZeD ]&ZeD ]!Ze                     eee                     "'ddgZe                    d           er*e                    d           e                    d            ede	 	          g edd          g edd          geedZddhZddZdS )TestParallelBackendBasez6
    Base class for testing the parallel backends
    T)nopython)r   cache)r   nogilparallel)r   ro   )r   ro   r   )r   r   )r   r   r         	threadingrS   multiprocessing_spawnmultiprocessing_forkmultiprocessing_forkserver)concurrent_jitconcurrent_vectorizeconcurrent_guvectorizeconcurrent_mix_useconcurrent_mix_use_masksomptbbc                    t          | j        j                  | _        t	          d| j                  5  |dk    rt          |           n|dk    rt          |           n|dk    rt          |           n|dk    rt          |           n|dk    rt          |           n|dk    rnt
          t          g}t          r4|                    t                     |                    t                     t          j        |           |D ]} ||           nt          d|z            d d d            d S # 1 swxY w Y   d S )	N	CACHE_DIRr   r   r   r   multiprocessing_defaultrS   zUnknown parallelism supplied %s)r   	__class__r4   
_cache_dirr   thread_implfork_proc_implforkserver_proc_implspawn_proc_impldefault_proc_impl_HAVE_OS_FORKr|   rS   shuffle
ValueError)r1   re   parallelismpsimpls        r   r   z#TestParallelBackendBase.run_compile  s   ()@AA[$/:: 	E 	Ek))F#### 666v&&&& <<<$V,,,, 777'''' 999!&))))((!?3  4IIn---II2333r""" ! !DDLLLL! !5CE E E+	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	Es   C5D66D:=D:N)r   )r4   r5   r6   __doc__r8   rN   rQ   rW   	all_impls_parfors_unsupportedparfor_implsextendr   NUMBA_NUM_THREADSmasks
mask_implsr   rJ   r|   rG   r   r   runnerssafe_backendsr   r&   r   r   r   r      s        
 	
D!!!
D---
D---t$$$t4000$'''$z:::$zFFFD)))D<<<D4HHHI   'Jt444Jt4@@@M4$777M4$dCCC	
 	&&&!##AJ 7 7 	7 	7Dkk$556666	7 )K./// 912227888 J4H0HJJJ
 d:>>>!
 Z@@@#
 ($. G ENME E E E E Er   r   )r   r   	workqueuezThreading layer not explicitc                   (    e Zd ZdZed             ZdS )TestParallelBackendav   These are like the numba.tests.test_threadsafety tests but designed
    instead to torture the parallel backend.
    If a suitable backend is supplied via NUMBA_THREADING_LAYER these tests
    can be run directly. This test class cannot be run using the multiprocessing
    option to the test runner (i.e. `./runtests -m`) as daemon processes cannot
    have children.
    c                     | j         D ]S}| j                                        D ]7\  }}d|z   dz   |z   }d } |||          }||_        t	          | ||           8Td S )Ntest_rh   c                       fd}|S )Nc                     t          j                    }|j        rd}|                     |           d S |                                d S )Nz)daemonized processes cannot have children)r   )r   current_processdaemonskipTestr   )r1   selfprocr   r   ps      r   test_methodzBTestParallelBackend.generate.<locals>.methgen.<locals>.test_methodJ  sX    #2#B#D#D#? B#ND MM$///// ,,Tq,AAAAAr   r&   )r   r   r   s   `` r   methgenz-TestParallelBackend.generate.<locals>.methgenI  s0    B B B B B B '&r   )r   r   itemsr4   setattr)clsr   namer   methnamer   ri   s          r   generatezTestParallelBackend.generateC  s     	+ 	+A!k//11 + +
d"Q;,t3	' 	' 	' WT1%%&Xr****+	+ 	+r   N)r4   r5   r6   r   classmethodr   r&   r   r   r   r   6  s9          + + [+ + +r   r   c                   D    e Zd Zee ej        dd          dZd Zd Z	dS )TestInSubprocessF r   r   r   c                 
   t          j        |t           j        t           j        |          }t          j        t
          |j                  }	 |                                 |                                \  }}|j	        dk    r-t          d|j	        d|                                d          |                                |                                f|                                 S # |                                 w xY w)Nstdoutstderrenvr   process failed with code : stderr follows
rv   
subprocessPopenPIPEr   Timer_TEST_TIMEOUTkillry   communicate
returncodeAssertionErrordecodecancelr1   cmdliner   popentimeoutr+   errs          r   run_cmdzTestInSubprocess.run_cmd`  s     (2(2%(* * *
 /-<<		MMOOO((**HC1$$$n%%%szz||||56 6 6 ::<<-NNGNNs   B
C, ,Dc                     t           j                                        }t          |          |d<   t          j        dd|g}|                     ||          S )NNUMBA_THREADING_LAYERz-mznumba.runtests)osenvironcopystrsys
executabler   )r1   testthreading_layerenv_copyr   s        r   run_test_in_separate_processz-TestInSubprocess.run_test_in_separate_processs  sK    :??$$,/,@,@()>4)94@||GX...r   N)
r4   r5   r6   skip_no_tbbskip_no_ompunittestskipIfbackendsr   r  r&   r   r   r   r   [  sU        "",X_UB779 9H  &/ / / / /r   r   c                   B    e Zd ZdZdZed             Zed             ZdS )TestSpecificBackenda  
    This is quite contrived, for each test in the TestParallelBackend tests it
    generates a test that will run the TestParallelBackend test in a new python
    process with an environment modified to ensure a specific threadsafe backend
    is used. This is with view of testing the backends independently and in an
    isolated manner such that if they hang/crash/have issues, it doesn't kill
    the test suite.
    Fc           	         
 | j         }t          j        }d|z   dz   |z   }|d|d|

fd}d|d|d}	t          | |	 t	          d           ||                               d S )Nr   rh   .c                 z   |                                \  }}| j        rt          d|d|d           t          j        d|          }|(|                     |                    d                     |                     d|           |                     d|v           |                     d|v           d S )	Nz
stdout:
 "z"
 stderr:
 ""z\.\.\. skipped '(.*?)'r   OKFAILERROR)	r  _DEBUGprintresearchr   groupassertIn
assertTrue)r1   orj   mbackendinjected_methods       r   test_templatez2TestSpecificBackend._inject.<locals>.test_template  s    44_gNNDAq{ B111aaa@AAA 	3Q77A}aggajj)))MM$"""OOF!O,,,OOG1,-----r   long_running)r5   r   r4   r   r
   )r   r   r   r  backend_guardthemodtheclsr   r  injected_testr  s      `      @r   _injectzTestSpecificBackend._inject  s    $-Q;$t+(.A	. 	. 	. 	. 	. 	. 	. ,-11dddGG<]#N##MM-$@$@AA	C 	C 	C 	C 	Cr   c           	      *   | j                                         D ]x\  }}| j        D ]k}| j                                        D ]O}|dv r&|dk    r t
          j                            d          r,|dv r|dk    r7|                     ||||           Plyd S )N)r   rS   r   linux)r   rS   r   )	r  r   r   r   keysr   platform
startswithr!  )r   r  r  r   r   s        r   r   zTestSpecificBackend.generate  s    &)l&8&8&:&: 	A 	A"G]_ A AK,,.. A AD ???5((L33G<< )  444#{22 KK4-@@@@AA	A 	Ar   N)r4   r5   r6   r   r  r   r!  r   r&   r   r   r  r  z  sa          FC C [C. A A [A A Ar   r  c                   b    e Zd ZdZdej                            e          z  Zddeiz  Z	ddZ
dS )ThreadLayerTestHelperzP
    Helper class for running an isolated piece of code based on a template
    z%ra  if 1:
    import sys
    sys.path.insert(0, "%(here)r")
    import multiprocessing
    import numpy as np
    from numba import njit
    import numba
    try:
        import threading_backend_usecases
    except ImportError as e:
        print("DEBUG:", sys.path)
        raise e
    import os

    sigterm_handler = threading_backend_usecases.sigterm_handler
    busy_func = threading_backend_usecases.busy_func

    def the_test():
        %%s

    if __name__ == "__main__":
        the_test()
    hereNc                 r   |0t           j                                        }t          d          |d<   t	          j        |t          j        t          j        |          }t          j        t          |j
                  }	 |                                 |                                \  }}|j        dk    r-t          d|j        d|                                d          	 |                                 n# |                                 w xY w|                                |                                fS )Nr   r   r   r   r   r   rv   )r   r   r   r   r   r   r   r   r   r   r   ry   r   r   r   r   r   r   s          r   r   zThreadLayerTestHelper.run_cmd  s   ;*//##C+.u::C'( (2(2%(* * *
 /-<<	MMOOO((**HC1$$$n%%%szz||||56 6 6 %
 NNGNNzz||SZZ\\))s   ?A#C8 8Dr   )r4   r5   r6   r   r   pathdirname__file___heretemplater   r&   r   r   r(  r(    sa         
 27??8,,,E, 5/-H0* * * * * *r   r(  c                   l    e Zd ZdZdZee ej        dd          dZ	e
d             Ze
d             ZdS )TestThreadingLayerSelectionz@
    Checks that numba.threading_layer() reports correctly.
    Fr   r   c           	      |    fd}dz  }t          | | t          d           ||                               d S )Nc                 
   d}| j         |z  z  }t          j        d|g}t          j                                        }t                    |d<   |                     ||          \  }}| j        rt          ||           d S d S )Nzif 1:
                X = np.arange(1000000.)
                Y = np.arange(1000000.)
                Z = busy_func(X, Y)
                assert numba.threading_layer() == '%s'
            -cr   r   )
r/  r   r   r   r   r   r   r   r  r  )r1   bodyrunmer   r   r+   r   r  s          r   r  z:TestThreadingLayerSelection._inject.<locals>.test_template  s    D MTG^4E~tU3G*//##C+.w<<C'(||G|55HC{  c3   r   z test_threading_layer_selector_%s	important)r   r
   )r   r  r  r  r   s    `   r   r!  z#TestThreadingLayerSelection._inject  sl    	  	  	  	  	  ;WD] K  }!=!=>>	@ 	@ 	@ 	@ 	@r   c                 p    | j                                         D ]\  }}|                     ||           d S r   )r  r   r!  )r   r  r  s      r   r   z$TestThreadingLayerSelection.generate  sE    &)l&8&8&:&: 	0 	0"G]KK////	0 	0r   N)r4   r5   r6   r   r  r  r  r  r  r  r   r!  r   r&   r   r   r1  r1    s          F"",X_UB779 9H @ @ [@( 0 0 [0 0 0r   r1  c                       e Zd ZdefdZeed                         Zeed                         Zed             Z	ed             Z
d ZdS )	TestThreadingLayerPriorityenv_varc                     t           j                                        }d|d<   ||d<   d| d}t          j        dt          j        |          g}|                     ||           dS )	zJTest setting priority via env var NUMBA_THREADING_LAYER_PRIORITY.
        r   r   NUMBA_THREADING_LAYER_PRIORITYa  
                import numba

                # trigger threading layer decision
                # hence catching invalid THREADING_LAYER_PRIORITY
                @numba.jit(
                    'float64[::1](float64[::1], float64[::1])',
                    nopython=True,
                    parallel=True,
                )
                def plus(x, y):
                    return x + y

                captured_envvar = list("a	  ".split())
                assert numba.config.THREADING_LAYER_PRIORITY ==                     captured_envvar, "priority mismatch"
                assert numba.threading_layer() == captured_envvar[0],                    "selected backend mismatch"
                r4  r5  N)r   r   r   r   r   textwrapdedentr   )r1   r<  r   codecmds        r   each_env_varz'TestThreadingLayerPriority.each_env_var  s     joo'0#$07,- *1  ( NOD!!

 	Sc"""""r   c                     g d}t          j        |          D ],}d                    |          }|                     |           -d S )Nr    )	itertoolspermutationsrz   rC  )r1   r   r   r<  s       r   test_valid_env_varz-TestThreadingLayerPriority.test_valid_env_var8  sY     .--'00 	' 	'AhhqkkGg&&&&	' 	'r   c                     d}|                      t                    5 }|                     |           d d d            n# 1 swxY w Y   dD ]+}|                     | t	          |j                             ,d S )Nztbb omp workqueue notvalidhere)z!THREADING_LAYER_PRIORITY invalid:zIt must be a permutation of)assertRaisesr   rC  r  r   	exception)r1   r<  raisesmsgs       r   test_invalid_env_varz/TestThreadingLayerPriority.test_invalid_env_var@  s     3~.. 	'&g&&&	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	'
 	; 	;C MMS(C(8$9$9::::		; 	;s   ?AAc                 :    dD ]}|                      |           d S )N)zomp tbb workqueuezomp workqueue tbbrC  r1   r<  s     r   test_ompz#TestThreadingLayerPriority.test_ompL  2    A 	' 	'Gg&&&&	' 	'r   c                 :    dD ]}|                      |           d S )N)ztbb omp workqueueztbb workqueue omprP  rQ  s     r   test_tbbz#TestThreadingLayerPriority.test_tbbQ  rS  r   c                 :    dD ]}|                      |           d S )N)zworkqueue tbb ompzworkqueue omp tbbrP  rQ  s     r   test_workqueuez)TestThreadingLayerPriority.test_workqueueV  s2    A 	' 	'Gg&&&&	' 	'r   N)r4   r5   r6   r   rC  r  r  rH  rN  rR  rU  rW  r&   r   r   r;  r;    s        #C # # # #B ' ' [ [' ; ; [ [; ' ' [' ' ' ['' ' ' ' 'r   r;  c                   |    e Zd ZdZdZed             Zed             Zd Z	 e
j        ed          d             ZdS )	TestMiscBackendIssueszL
    Checks fixes for the issues with threading backends implementation
    Fc                     d}t           j        d|g}t          j                                        }d|d<   d|d<   |                     ||           dS )	z8
        Tests that OMP does not overflow stack
        a  if 1:
            from numba import vectorize, threading_layer
            import numpy as np

            @vectorize(['f4(f4,f4,f4,f4,f4,f4,f4,f4)'], target='parallel')
            def foo(a, b, c, d, e, f, g, h):
                return a+b+c+d+e+f+g+h

            x = np.ones(2**20, np.float32)
            foo(*([x]*8))
            assert threading_layer() == "omp", "omp not found"
        r4  r   r   100KOMP_STACKSIZEr5  Nr   r   r   r   r   r   r1   r7  r   r   s       r   test_omp_stack_overflowz-TestMiscBackendIssues.test_omp_stack_overflowb  s[    
 >4/joo',#$%OW#&&&&&r   c                     d}t           j        d|g}t          j                                        }d|d<   d|d<   |                     ||           dS )	zq
        Tests that TBB works well with single thread
        https://github.com/numba/numba/issues/3440
        aM  if 1:
            from numba import njit, prange, threading_layer

            @njit(parallel=True)
            def foo(n):
                acc = 0
                for i in prange(n):
                    acc += i
                return acc

            foo(100)
            assert threading_layer() == "tbb", "tbb not found"
        r4  r   r   1r   r5  Nr]  r^  s       r   test_single_thread_tbbz,TestMiscBackendIssues.test_single_thread_tbby  s\     >4/joo',#$#& W#&&&&&r   c                    d}t           j        d|g}t          j                                        }d|d<   d|d<   	 |                     ||          \  }}d
S # t          $ r_}| j        rt          ||           t          |          }| 
                    d|           d	}| 
                    ||           Y d
}~d
S d
}~ww xY w)zW
        Tests workqueue raises sigabrt if a nested parallel call is performed
        a  if 1:
            from numba import njit, prange
            import numpy as np

            @njit(parallel=True)
            def nested(x):
                for i in prange(len(x)):
                    x[i] += 1


            @njit(parallel=True)
            def main():
                Z = np.zeros((5, 10))
                for i in prange(Z.shape[0]):
                    nested(Z[i])
                return Z

            main()
        r4  r   r   4r   r5  zfailed with codezTNumba workqueue threading layer is terminating: Concurrent access has been detected.N)r   r   r   r   r   r   r   r  r  r   r  )	r1   r7  r   r   r+   r   rj   e_msgrA   s	            r   +test_workqueue_aborts_on_nested_parallelismzATestMiscBackendIssues.test_workqueue_aborts_on_nested_parallelism  s    & >4/joo'2#$#& 	+||G|55HC 		+ 		+ 		+{  c3FFEMM,e444?HMM(E*********		+s   A 
C !AB;;C zTest needs fork(2)c                     d}t           j        d|g}t          j                                        }d|d<   d|d<   |                     ||           d S )Na  if 1:
            from numba import njit, prange, threading_layer
            import numpy as np
            import multiprocessing

            if __name__ == "__main__":
                # Need for force fork context (OSX default is "spawn")
                multiprocessing.set_start_method('fork')

                @njit(parallel=True)
                def func(x):
                    return 10. * x

                arr = np.arange(2.)

                # run in single process to start Numba's thread pool
                np.testing.assert_allclose(func(arr), func.py_func(arr))

                # now run in a multiprocessing pool to get a fork from a
                # non-main thread
                with multiprocessing.Pool(10) as p:
                    result = p.map(func, [arr])
                np.testing.assert_allclose(result,
                                           func.py_func(np.expand_dims(arr, 0)))

                assert threading_layer() == "workqueue"
        r4  r   r   rd  r   r5  r]  r^  s       r   0test_workqueue_handles_fork_from_non_main_threadzFTestMiscBackendIssues.test_workqueue_handles_fork_from_non_main_thread  s\    6 >4/joo'2#$#& W#&&&&&r   N)r4   r5   r6   r   r  r  r_  r  rb  rf  r  
skipUnlessr   rh  r&   r   r   rY  rY  [  s          F' ' [', ' ' ['0'+ '+ '+R X(<==&' &' >=&' &' &'r   rY  c                   `    e Zd ZdZdZd Zd Zd Zed             Z	d Z
d Zed	             Zd
S )TestForkSafetyIssueszV
    Checks Numba's behaviour in various situations involving GNU OpenMP and fork
    Fc                 X    d}t           j        d|g}|                     |          \  }}d S )Nzsif 1:
            from numba.np.ufunc import omppool
            assert omppool.openmp_vendor == 'GNU'
            r4  )r   r   r   )r1   r7  r   r+   r   s        r   !test_check_threading_layer_is_gnuz6TestForkSafetyIssues.test_check_threading_layer_is_gnu  s2     >4/<<((SSSr   c                     d}| j         |z  }t          j        d|g}	 |                     |          \  }}dS # t          $ r.}|                     dt          |                     Y d}~dS d}~ww xY w)z~
        Whilst normally valid, this actually isn't for Numba invariant of OpenMP
        Checks SIGABRT is received.
        zif 1:
            X = np.arange(1000000.)
            Y = np.arange(1000000.)
            Z = busy_func(X, Y)
            pid = os.fork()
            if pid  == 0:
                Z = busy_func(X, Y)
            else:
                os.wait()
        r4  zfailed with code -6N)r/  r   r   r   r   r  r   )r1   r6  r7  r   r+   r   rj   s          r   !test_par_parent_os_fork_par_childz6TestForkSafetyIssues.test_par_parent_os_fork_par_child  s    
	 $>4/	9||G,,HC 	9 	9 	9MM/Q888888888	9s   7 
A/#A**A/c                     d}| j         |z  }t          j        d|g}|                     |          \  }}| j        rt          ||           dS dS )au  
        Implicit use of multiprocessing fork context.
        Does this:
        1. Start with OpenMP
        2. Fork to processes using OpenMP (this is invalid)
        3. Joins fork
        4. Check the exception pushed onto the queue that is a result of
           catching SIGTERM coming from the C++ aborting on illegal fork
           pattern for GNU OpenMP
        a  if 1:
            mp = multiprocessing.get_context('fork')
            X = np.arange(1000000.)
            Y = np.arange(1000000.)
            q = mp.Queue()

            # Start OpenMP runtime on parent via parallel function
            Z = busy_func(X, Y, q)

            # fork() underneath with no exec, will abort
            proc = mp.Process(target = busy_func, args=(X, Y, q))
            proc.start()

            err = q.get()
            assert "Caught SIGTERM" in str(err)
        r4  Nr/  r   r   r   r  r  r1   r6  r7  r   r+   r   s         r   *test_par_parent_implicit_mp_fork_par_childz?TestForkSafetyIssues.test_par_parent_implicit_mp_fork_par_child  s_      $>4/<<((S; 	#sOOOOO	 	r   c                     d}| j         |z  }t          j        d|g}|                     |          \  }}| j        rt          ||           dS dS )au  
        Explicit use of multiprocessing fork context.
        Does this:
        1. Start with OpenMP
        2. Fork to processes using OpenMP (this is invalid)
        3. Joins fork
        4. Check the exception pushed onto the queue that is a result of
           catching SIGTERM coming from the C++ aborting on illegal fork
           pattern for GNU OpenMP
        a  if 1:
            X = np.arange(1000000.)
            Y = np.arange(1000000.)
            ctx = multiprocessing.get_context('fork')
            q = ctx.Queue()

            # Start OpenMP runtime on parent via parallel function
            Z = busy_func(X, Y, q)

            # fork() underneath with no exec, will abort
            proc = ctx.Process(target = busy_func, args=(X, Y, q))
            proc.start()
            proc.join()

            err = q.get()
            assert "Caught SIGTERM" in str(err)
        r4  Nrq  rr  s         r   *test_par_parent_explicit_mp_fork_par_childz?TestForkSafetyIssues.test_par_parent_explicit_mp_fork_par_child-  s_    " $>4/<<((S; 	#sOOOOO	 	r   c                     d}| j         |z  }t          j        d|g}|                     |          \  }}| j        rt          ||           dS dS )z
        Explicit use of multiprocessing spawn, this is safe.
        Does this:
        1. Start with OpenMP
        2. Spawn to processes using OpenMP
        3. Join spawns
        4. Run some more OpenMP
        a  if 1:
            X = np.arange(1000000.)
            Y = np.arange(1000000.)
            ctx = multiprocessing.get_context('spawn')
            q = ctx.Queue()

            # Start OpenMP runtime and run on parent via parallel function
            Z = busy_func(X, Y, q)
            procs = []
            for x in range(20): # start a lot to try and get overlap
                ## fork() + exec() to run some OpenMP on children
                proc = ctx.Process(target = busy_func, args=(X, Y, q))
                procs.append(proc)
                sys.stdout.flush()
                sys.stderr.flush()
                proc.start()

            [p.join() for p in procs]

            try:
                q.get(False)
            except multiprocessing.queues.Empty:
                pass
            else:
                raise RuntimeError("Queue was not empty")

            # Run some more OpenMP on parent
            Z = busy_func(X, Y, q)
        r4  Nrq  rr  s         r   -test_par_parent_mp_spawn_par_child_par_parentzBTestForkSafetyIssues.test_par_parent_mp_spawn_par_child_par_parentP  s_    : $>4/<<((S; 	#sOOOOO	 	r   c                     d}| j         |z  }t          j        d|g}|                     |          \  }}| j        rt          ||           dS dS )a  
        Implicit use of multiprocessing (will be fork, but cannot declare that
        in Py2.7 as there's no process launch context).
        Does this:
        1. Start with no OpenMP
        2. Fork to processes using OpenMP
        3. Join forks
        4. Run some OpenMP
        a,  if 1:
            X = np.arange(1000000.)
            Y = np.arange(1000000.)
            q = multiprocessing.Queue()

            # this is ok
            procs = []
            for x in range(10):
                # fork() underneath with but no OpenMP in parent, this is ok
                proc = multiprocessing.Process(target = busy_func,
                                               args=(X, Y, q))
                procs.append(proc)
                proc.start()

            [p.join() for p in procs]

            # and this is still ok as the OpenMP happened in forks
            Z = busy_func(X, Y, q)
            try:
                q.get(False)
            except multiprocessing.queues.Empty:
                pass
            else:
                raise RuntimeError("Queue was not empty")
        r4  Nrq  rr  s         r   =test_serial_parent_implicit_mp_fork_par_child_then_par_parentzRTestForkSafetyIssues.test_serial_parent_implicit_mp_fork_par_child_then_par_parent|  _    2 $>4/<<((S; 	#sOOOOO	 	r   c                     d}| j         |z  }t          j        d|g}|                     |          \  }}| j        rt          ||           dS dS )z
        Explicit use of multiprocessing 'fork'.
        Does this:
        1. Start with no OpenMP
        2. Fork to processes using OpenMP
        3. Join forks
        4. Run some OpenMP
        a  if 1:
            X = np.arange(1000000.)
            Y = np.arange(1000000.)
            ctx = multiprocessing.get_context('fork')
            q = ctx.Queue()

            # this is ok
            procs = []
            for x in range(10):
                # fork() underneath with but no OpenMP in parent, this is ok
                proc = ctx.Process(target = busy_func, args=(X, Y, q))
                procs.append(proc)
                proc.start()

            [p.join() for p in procs]

            # and this is still ok as the OpenMP happened in forks
            Z = busy_func(X, Y, q)
            try:
                q.get(False)
            except multiprocessing.queues.Empty:
                pass
            else:
                raise RuntimeError("Queue was not empty")
        r4  Nrq  rr  s         r   =test_serial_parent_explicit_mp_fork_par_child_then_par_parentzRTestForkSafetyIssues.test_serial_parent_explicit_mp_fork_par_child_then_par_parent  rz  r   N)r4   r5   r6   r   r  rm  ro  rs  r   ru  rw  ry  r|  r&   r   r   rk  rk    s          F) ) )9 9 9,  B     Z D* * *X' ' 'R & & Z& & &r   rk  c                   >    e Zd ZdZed             Zed             ZdS )TestTBBSpecificIssuesFc                     d}t           j        d|g}|                     |          \  }}d}|                     ||           | j        r"t          d|           t          d|           d S d S )Na%  if 1:
            import threading
            import numba
            numba.config.THREADING_LAYER='tbb'
            from numba import njit, prange, objmode
            from numba.core.serialize import PickleCallableByPath
            import os

            e_running = threading.Event()
            e_proceed = threading.Event()

            def indirect_core():
                e_running.set()
                # wait for forker() to have forked
                while not e_proceed.isSet():
                    pass

            indirect = PickleCallableByPath(indirect_core)

            @njit
            def obj_mode_func():
                with objmode():
                    indirect()

            @njit(parallel=True, nogil=True)
            def work():
                acc = 0
                for x in prange(10):
                    acc += x
                obj_mode_func()
                return acc

            def runner():
                work()

            def forker():
                # wait for the jit function to say it's running
                while not e_running.isSet():
                    pass
                # then fork
                os.fork()
                # now fork is done signal the runner to proceed to exit
                e_proceed.set()

            numba_runner = threading.Thread(target=runner,)
            fork_runner =  threading.Thread(target=forker,)

            threads = (numba_runner, fork_runner)
            for t in threads:
                t.start()
            for t in threads:
                t.join()
        r4  z9Attempted to fork from a non-main thread, the TBB libraryOUT:ERR:)r   r   r   r  r  r  )r1   r7  r   r+   r   msg_heads         r   test_fork_from_non_main_threadz4TestTBBSpecificIssues.test_fork_from_non_main_thread  s    64l >4/<<((SNh$$$; 	&#&#	 	r   c                    |                                   d}d                    d|          }t          j        d|g}t          j                                        }d|d<   |                     ||          \  }}||v r|                     d           n| 	                    d	|           | j
        r"t          d
|           t          d|           d S d S )NzSKIP: COMPILATION FAILEDax  if 1:
            import ctypes
            import sys
            import multiprocessing as mp
            from tempfile import TemporaryDirectory, NamedTemporaryFile
            from numba.pycc.platform import Toolchain, external_compiler_works
            from numba import njit, prange, threading_layer
            import faulthandler
            faulthandler.enable()
            if not external_compiler_works():
                raise AssertionError('External compilers are not found.')
            with TemporaryDirectory() as tmpdir:
                with NamedTemporaryFile(dir=tmpdir) as tmpfile:
                    try:
                        src = """
                        #define TBB_PREVIEW_WAITING_FOR_WORKERS 1
                        #include <tbb/tbb.h>
                        static tbb::task_scheduler_handle tsh;
                        extern "C"
                        {
                        void launch(void)
                        {
                            tsh = tbb::task_scheduler_handle::get();
                        }
                        }
                        """
                        cxxfile = f"{tmpfile.name}.cxx"
                        with open(cxxfile, 'wt') as f:
                            f.write(src)
                        tc = Toolchain()
                        object_files = tc.compile_objects([cxxfile,],
                                                           output_dir=tmpdir)
                        dso_name = f"{tmpfile.name}.so"
                        tc.link_shared(dso_name, object_files,
                                       libraries=['tbb',],
                                       export_symbols=['launch'])
                        # Load into the process, it doesn't matter whether the
                        # DSO exists on disk once it's loaded in.
                        DLL = ctypes.CDLL(dso_name)
                    except Exception as e:
                        # Something is broken in compilation, could be one of
                        # many things including, but not limited to: missing tbb
                        # headers, incorrect permissions, compilers that don't
                        # work for the above
                        print(e)
                        print('BROKEN_COMPILERS')
                        sys.exit(0)

                    # Do the test, launch this library and also execute a
                    # function with the TBB threading layer.

                    DLL.launch()

                    @njit(parallel=True)
                    def foo(n):
                        acc = 0
                        for i in prange(n):
                            acc += i
                        return acc

                    foo(1)

            # Check the threading layer used was TBB
            assert threading_layer() == 'tbb'

            # Use mp context for a controlled version of fork, this triggers the
            # reported bug.

            ctx = mp.get_context('fork')
            def nowork():
                pass
            p = ctx.Process(target=nowork)
            p.start()
            p.join(10)
            print("SUCCESS")
            BROKEN_COMPILERSr4  r   r   r5  z3Compilation of DSO failed. Check output for detailsSUCCESSr  r  )skip_if_no_external_compilerreplacer   r   r   r   r   r   r   r  r  r  )r1   r  r7  r   r   r+   r   s          r   &test_lifetime_of_task_scheduler_handlez<TestTBBSpecificIssues.test_lifetime_of_task_scheduler_handle0  s     	))+++ 6KV *,<==W 	Z >4/joo',#$<<S<11Ss""MMOPPPPMM)S))); 	&#&#	 	r   N)r4   r5   r6   r  r   r  r  r&   r   r   r~  r~    sX         FX X ZXt _ _ Z_ _ _r   r~  c                   4    e Zd ZdZd Zed             Zd ZdS )TestInitSafetyIssuesFc                    t          j        |t           j        t           j                  }t          j        t
          |j                  }	 |                                 |                                \  }}|j	        dk    r-t          d|j	        d|                                d          	 |                                 n# |                                 w xY w|                                |                                fS )N)r   r   r   r   r   rv   r   )r1   r   r   r   r+   r   s         r   r   zTestInitSafetyIssues.run_cmd  s     (2(2: : : /-<<	MMOOO((**HC1$$$n%%%szz||||56 6 6 %
 NNGNNzz||SZZ\\))s   A#C Cc                 T   t           j                            t           j                            t                    d          }t
          j        |g}|                     |          \  }}|                     d|           | j	        r"t          d|           t          d|           d S d S )Nzorphaned_semaphore_usecase.pyzleaked semaphorer  r  )r   r+  rz   r,  r-  r   r   r   assertNotInr  r  )r1   	test_filer   r+   r   s        r   test_orphaned_semaphorez,TestInitSafetyIssues.test_orphaned_semaphore  s    
 GLL!:!:!@B B	>9-<<((S 	+S111; 	&#&#	 	r   c                 N   dD ]}	 t          j        |           n# t          $ r Y $w xY wd}t          j        d|                    |          g}|                     |          \  }}| j        r t          d|           t          d|           | 	                    ||           d S )N)r   r   r   zimport numba; import multiprocessing;multiprocessing.set_start_method('{}');print(multiprocessing.get_context().get_start_method())r4  r  r  )
r   r   r   r   r   formatr   r  r  r  )r1   methrB  r   r+   r   s         r   test_lazy_lock_initz(TestInitSafetyIssues.test_lazy_lock_init  s     4 	% 	%D+D1111   MC ~tSZZ-=-=>G||G,,HC{ #fc"""fc"""MM$$$$$	% 	%s   
((N)r4   r5   r6   r  r   r   r  r  r&   r   r   r  r    sT         F* * *"   Z % % % % %r   r  c                       e Zd Zd ZdS )TestOpenMPVendorsc                     t                      }d|d<   d|d<   d|d<   |                                D ]G}t          j                            |          r&|                     ||         t          j                   HdS )z>
        Checks the OpenMP vendor strings are correct
        MSwin32Intelr   r   r#  N)dictr$  r   r%  r&  assertEqualr   openmp_vendor)r1   rA   ks      r   test_vendorszTestOpenMPVendors.test_vendors  s     66 $!  	E 	EA|&&q)) E  !g.CDDD	E 	Er   N)r4   r5   r6   r  r&   r   r   r  r    s(        E E E E Er   r  __main__)cr   r]   rF  r   r   rS   r  r   r   r?  r   r  numpyr   numbar   r   r   r   numba.tests.supportr   r   r	   r
   r   r   r[   t_queuenumba.testing.mainr   _RUNNER_TIMEOUT
numba.corer   r   numba.np.ufunc.parallelr   numba.np.ufuncr   _HAVE_TBB_POOLImportErrorr   _HAVE_OMP_POOLscipy.linalg.cython_lapackscipy_HAVE_LAPACKri  r  r  r  _gnuompskip_unless_gnu_ompr%  r&  _windows_osxmaxsize_32bitr   r   r   r#   r)   r,   objectr.   r8   rG   rN   rQ   rW   rk   r   Thread_thread_classr   r   r   r   r   r   r   r   r   THREADING_LAYER_specific_backendsr   r   r   r  r(  r1  r;  rY  rk  r~  r  r  r4   mainr&   r   r   <module>r     sR                				  				     



           > > > > > > > > > > > >G G G G G G G G G G G G G G G G     : : : : : :        #%
EEEEEE!!###&&&&&&NN   NNN&&&&&&NN   NNN%%%%LL   LLL "h!.2NOO!h!.2KLL

;W2e;)h)'3JKK <""5))
|x((		 
     $ $ $ $     
             v      
2 2 2 2 2 2 2 2
 
 
 
 
& 
 
 
2 2 2 2 2H 2 2 22 2 2 2 2x 2 2 22 2 2 2 2 2 2 2    (  , , , , ,v , , ,   omW];;!/??7#;#;< K$_oof&=&=>N*?OOL,I,IJ $O__Y%?%?@ UE UE UE UE UEh UE UE UEp +/JJ  ')GHH+ + + + +1 + + IH+B      / / / / /v / / />5A 5A 5A 5A 5A*,C 5A 5A 5Ap      3* 3* 3* 3* 3*H 3* 3* 3*l "0 "0 "0 "0 "0"7 "0 "0 "0J  $ $ & & & C' C' C' C' C'!6 C' C' C'L F' F' F' F' F'1 F' F' F'T d d d d d0 d d  dN     1    D 9% 9% 9% 9% 9%8 9% 9% 9%x E E E E E E E  E$ zHMOOOOO s6   %A> >BBB BB#B* *B43B4