2015-04-10 23 views
6

Ich würde gerne wissen, ob es möglich ist, bei (Python) Runtime die maximale Anzahl von Threads zu ändern, die von OpenBLAS hinter numpy verwendet werden?Maximale Anzahl von Threads zur Laufzeit auf numpy/openblas setzen

Ich weiß, dass es möglich ist, es vor dem Ausführen des Interpreters über die Umgebungsvariable OMP_NUM_THREADS festzulegen, aber ich möchte es zur Laufzeit ändern.

Regel bei der Verwendung von MKL statt OpenBLAS ist es möglich:

import mkl 
mkl.set_num_threads(n) 
+2

Sie können versuchen, die Funktion 'openblas_set_num_threads' über das' ctypes'-Modul aufzurufen. Ähnlich wie [diese Frage] (http://stackoverflow.com/q/28283112/2379410) –

Antwort

10

Sie dies telefonisch tun, um die openblas_set_num_threads Funktion ctypes verwenden. Ich finde mich oft zu wollen, dies zu tun, so schrieb ich ein wenig Kontext-Manager:

import contextlib 
import ctypes 
from ctypes.util import find_library 

# Prioritize hand-compiled OpenBLAS library over version in /usr/lib/ 
# from Ubuntu repos 
try_paths = ['/opt/OpenBLAS/lib/libopenblas.so', 
      '/lib/libopenblas.so', 
      '/usr/lib/libopenblas.so.0', 
      find_library('openblas')] 
openblas_lib = None 
for libpath in try_paths: 
    try: 
     openblas_lib = ctypes.cdll.LoadLibrary(libpath) 
     break 
    except OSError: 
     continue 
if openblas_lib is None: 
    raise EnvironmentError('Could not locate an OpenBLAS shared library', 2) 


def set_num_threads(n): 
    """Set the current number of threads used by the OpenBLAS server.""" 
    openblas_lib.openblas_set_num_threads(int(n)) 


# At the time of writing these symbols were very new: 
# https://github.com/xianyi/OpenBLAS/commit/65a847c 
try: 
    openblas_lib.openblas_get_num_threads() 
    def get_num_threads(): 
     """Get the current number of threads used by the OpenBLAS server.""" 
     return openblas_lib.openblas_get_num_threads() 
except AttributeError: 
    def get_num_threads(): 
     """Dummy function (symbol not present in %s), returns -1.""" 
     return -1 
    pass 

try: 
    openblas_lib.openblas_get_num_procs() 
    def get_num_procs(): 
     """Get the total number of physical processors""" 
     return openblas_lib.openblas_get_num_procs() 
except AttributeError: 
    def get_num_procs(): 
     """Dummy function (symbol not present), returns -1.""" 
     return -1 
    pass 


@contextlib.contextmanager 
def num_threads(n): 
    """Temporarily changes the number of OpenBLAS threads. 

    Example usage: 

     print("Before: {}".format(get_num_threads())) 
     with num_threads(n): 
      print("In thread context: {}".format(get_num_threads())) 
     print("After: {}".format(get_num_threads())) 
    """ 
    old_n = get_num_threads() 
    set_num_threads(n) 
    try: 
     yield 
    finally: 
     set_num_threads(old_n) 

Sie können es wie folgt verwenden:

with num_threads(8): 
    np.dot(x, y) 

Wie in den Kommentaren erwähnt, openblas_get_num_threads und openblas_get_num_procs waren sehr neu Funktionen zum Zeitpunkt des Schreibens und sind daher möglicherweise erst verfügbar, wenn Sie OpenBLAS mit der neuesten Version des Quellcodes kompiliert haben.

+2

beachten Sie, dass ab v0.2.14 Pthread openblas_get_num_procs Affinität nicht berücksichtigt, so dass es zu Überbelegung führen kann, wenn die Anzahl der verwendbaren CPUs ist eingeschränkt (zB in Containern), verwenden Sie stattdessen len (os.sched_getaffinity (0)) (python> = 3.3) – jtaylor

Verwandte Themen