2014-12-18 16 views
8

Ich muss oft große numpy Arrays (einige Milliarden Elemente) sortieren, was zu einem Engpass in meinem Code wurde. Ich suche nach einer Möglichkeit, es parallel zu machen.Parallele In-Place-Sortierung für numpy Arrays

Gibt es parallele Implementierungen für die ndarray.sort() Funktion? Das Numexpr-Modul bietet eine parallele Implementierung für die meisten mathematischen Operationen auf numpigen Arrays, aber es fehlen Sortiermöglichkeiten.

Vielleicht ist es möglich, einen einfachen Wrapper rund um eine C++ - Implementierung der parallelen Sortierung zu erstellen, und verwenden Sie es über Cython?

+0

Sie könnten Theano (http://deeplearning.net/software/theano/index.html) ansehen. Ich bin mir nicht sicher, ob seine sort() -Funktion parallel ist - aber es ist kompiliert und läuft auf einer GPU. – Dietrich

Antwort

2

Mergesort parallelisiert ganz natürlich. Lassen Sie jeden Worker einen beliebigen Chunk vorsortieren, und führen Sie dann einen einzigen Merge-Durchlauf für ihn aus. Das endgültige Zusammenführen sollte nur O (N) -Operationen erfordern, und es ist trivial, eine Funktion dafür in Numba oder dergleichen zu schreiben.

Wikipedia agrees

+0

Tatsächlich gibt es eine parallele Implementierung von stl sort, wie hier beschrieben: https://gcc.gnu.org/onlinedocs/libstdc++/manual/parallel_mode.html –

4

Ich landete GCC parallele Sortierung Verpackung. Hier ist der Code:

parallelSort.pyx

# cython: wraparound = False 
# cython: boundscheck = False 
import numpy as np 
cimport numpy as np 
import cython 
cimport cython 

ctypedef fused real: 
    cython.char 
    cython.uchar 
    cython.short 
    cython.ushort 
    cython.int 
    cython.uint 
    cython.long 
    cython.ulong 
    cython.longlong 
    cython.ulonglong 
    cython.float 
    cython.double 

cdef extern from "<parallel/algorithm>" namespace "__gnu_parallel": 
    cdef void sort[T](T first, T last) nogil 

def numpyParallelSort(real[:] a): 
    "In-place parallel sort for numpy types" 
    sort(&a[0], &a[a.shape[0]]) 

Extra-Compiler argumente: -fopenmp (kompiliert) und -lgomp (Verknüpfung)

Diese Make-Datei wird es tun:

all: 
    cython --cplus parallelSort.pyx 
    g++ -g -march=native -Ofast -fpic -c parallelSort.cpp -o parallelSort.o -fopenmp `python-config --includes` 
    g++ -g -march=native -Ofast -shared -o parallelSort.so parallelSort.o `python-config --libs` -lgomp 

clean: 
    rm -f parallelSort.cpp *.o *.so 

Und das zeigt, dass es funktioniert:

from parallelSort import numpyParallelSort 
import numpy as np 
a = np.random.random(100000000) 

numpyParallelSort(a) 
print a[:10] 

edit: behobener Fehler im Kommentar bemerkt

+2

Große Antwort, und funktioniert gut (sortiert 3,2 Milliarden Floats in unter zwei Minuten !!!) Allerdings gibt es einen interessanten Fehler. Wenn Sie am Ende der Liste 'a [-10: 0]' sehen, sehen Sie, dass das letzte Element des Originals nicht sortiert ist. Ich musste '& a [a.shape [0] -1]' in 'a [a.shape [0]]' ändern, um die richtige Sortierung zu erhalten. – Nelz11