Ich habe eine Python-Bibliothek mit dem Namen ** PyVideoCore ** für GPGPU auf Raspberry Pi erstellt, daher werde ich sie vorstellen.
Die Raspberry Pi-Serie ist mit der mobilen GPU ** VideoCore IV ** von Broadcom ausgestattet. Diese GPU wird offiziell im Referenzhandbuch (https://docs.broadcom.com/docs/12358545) veröffentlicht. Dies wurde von Broadcom als Geburtstagsgeschenk für die Raspberry Pi Foundation veröffentlicht im Februar 2014. Dank dieses Dokuments ist es möglich, VideoCore zu hacken.
VideoCore IV verfügt über 12 Quad Processing Units (** QPU **). Jede QPU ist ein 16-Wege-SIMD-Prozessor, der mit einem Befehl Vektorberechnungen mit 4 Wörtern x 4 Zyklen (dh 16 Längen) durchführt. Jede QPU kann gleichzeitig zwei Operationen ausführen, ein Additionssystem und ein Integrationssystem. Mit anderen Worten können bis zu 12 × 4 × 2 = 96 Operationen gleichzeitig auf der gesamten GPU ausgeführt werden. Da der Takt 250 MHz beträgt, beträgt die theoretische Leistung 96 × 0,25 = 24 GFP. Nur einfache Präzision. Raspberry Pi 2 scheint in der Lage zu sein, bis zu etwa 500 MHz zu übertakten.
Darüber hinaus gibt es drei von ALU unabhängige Special Function Units (SFU), und RECIP, RECIPSQRT, EXP2 und LOG2 können berechnet werden. Es verwendet jedoch 4 Anweisungen (16 Zyklen), kann nicht per Pipeline übertragen werden und weist eine schlechte Genauigkeit auf (ich habe nicht richtig experimentiert, aber es scheint, dass LOG2 mit Ausnahme von LOG2 etwa 4 Stellen hat), sodass es zur Rechenleistung der SFU beiträgt. Ist Minute. Jede QPU kann bis zu zwei Hardware-Threads ausführen. Mit anderen Worten, Sie können bis zu 24 Threads gleichzeitig ausführen. Die Zuweisung von Threads zur QPU erfolgt dynamisch durch den VideoCore-Scheduler. Es gibt einen Mutex und 16 Semaphore zum Synchronisieren von Threads. Es gibt verschiedene Arten von Speicher, je nachdem, wie Sie ihn verwenden, aber er wird länger sein, daher werde ich ihn später erläutern.
Es ist fast so. Die Leistung ist nicht hoch, weil es für Handys gedacht ist, aber ich denke, es wird interessant sein, damit zu spielen, weil Sie das komplette Dokument erhalten, es für ein paar tausend Yen kaufen können und es selten eine andere GPGPU als NVIDIA gibt. Wenn Sie ein Projekt mit einem Smartphone mit Raspberry Pi oder VideoCore IV durchführen, würde ich diese Rechenleistung natürlich begrüßen.
PyVideoCore
Leider verfügt VideoCore IV (wahrscheinlich) nicht über eine GPGPU-Entwicklungsumgebung wie CUDA oder OpenCL, sodass Sie in der Assemblersprache für QPU entwickeln müssen. Erstens gibt es keine Sprache oder Assembler. Die folgenden Projekte wurden in der Vergangenheit durchgeführt, aber es scheint, dass sie ihre eigenen Assembler entwickeln.
** PyVideoCore ** hat versucht, die Assemblersprache als Pythons internes DSL zu implementieren, um das Schreiben etwas zu vereinfachen. Das folgende Beispiel fügt nur einen Float-Vektor der Länge 16 hinzu. Sie können jedoch den Host-Code und den GPU-Code in eine Datei schreiben und als normales Python-Skript ausführen, ohne es zu kompilieren.
import numpy as np
from videocore.assembler import qpu
from videocore.driver import Driver
@qpu
def hello_world(asm):
# Load two vectors of length 16 from the host memory (address=uniforms[0]) to VPM
setup_dma_load(nrows=2)
start_dma_load(uniform)
wait_dma_load()
# Setup VPM read/write operaitons
setup_vpm_read(nrows=2)
setup_vpm_write()
# Compute a + b
mov(r0, vpm)
mov(r1, vpm)
fadd(vpm, r0, r1)
# Store the result vector from VPM to the host memory (address=uniforms[1])
setup_dma_store(nrows=1)
start_dma_store(uniform)
wait_dma_store()
# Finish the thread
exit()
with Driver() as drv:
# Input vectors
a = np.random.random(16).astype('float32')
b = np.random.random(16).astype('float32')
# Copy vectors to shared memory for DMA transfer
inp = drv.copy(np.r_[a, b])
out = drv.alloc(16, 'float32')
# Run the program
drv.execute(
n_threads=1,
program=drv.program(hello_world),
uniforms=[inp.address, out.address]
)
print ' a '.center(80, '=')
print(a)
print ' b '.center(80, '=')
print(b)
print ' a+b '.center(80, '=')
print(out)
print ' error '.center(80, '=')
print(np.abs(a+b-out))
Der Assembler-Code hat einen Dekorator namens "@ qpu". Derzeit ist es erforderlich, eine unformatierte Assembly zu schreiben, aber der GPU-Code selbst ist eine normale Funktion. Da jeder Befehl auch eine normale Funktion ist, ist es möglich, mithilfe von Python-Funktionen eine Bibliothek häufig verwendeter Muster zu erstellen. Überlegen.
Unten ist das Repository. Versuch es.
Ich denke von nun an daran, Benchmarks zu erstellen und Software zu erstellen, also schreibe ich noch einmal etwas.
Recommended Posts