J'ai créé une bibliothèque Python appelée ** PyVideoCore ** pour GPGPU sur Raspberry Pi, je vais donc la présenter.
La série Raspberry Pi est équipée du GPU mobile ** VideoCore IV ** de Broadcom. Ce GPU est officiellement publié dans le Guide de référence (https://docs.broadcom.com/docs/12358545). Cela a été publié par Broadcom comme cadeau d'anniversaire à la Fondation Raspberry Pi en février 2014. Grâce à ce document, il est possible de pirater VideoCore.
VideoCore IV dispose de 12 unités de traitement quadruples (** QPU **). Chaque QPU est un processeur SIMD à 16 voies qui effectue 4 mots x 4 cycles (soit 16 longueurs) des calculs vectoriels avec une instruction. Chaque QPU peut exécuter deux opérations, un système d'addition et un système d'intégration, en même temps. En d'autres termes, jusqu'à 12 × 4 × 2 = 96 opérations peuvent être exécutées simultanément sur l'ensemble du GPU. Puisque l'horloge est de 250 MHz, les performances théoriques sont de 96 × 0,25 = 24GFLOPS. Une seule précision. Raspberry Pi 2 semble pouvoir overclocker jusqu'à environ 500 MHz.
En outre, il existe trois unités de fonction spéciale (SFU) indépendantes de ALU, et RECIP, RECIPSQRT, EXP2 et LOG2 peuvent être calculés. Cependant, il utilise 4 instructions (16 cycles), ne peut pas être pipeliné et a une précision médiocre (je n'ai pas expérimenté correctement, mais il semble que LOG2 compte environ 4 chiffres sauf LOG2), il contribue donc à la puissance de calcul de SFU. Est minute. Chaque QPU peut exécuter jusqu'à deux threads matériels. En d'autres termes, vous pouvez exécuter jusqu'à 24 threads en même temps. L'affectation des threads au QPU est effectuée dynamiquement par le planificateur VideoCore. Il existe un mutex et 16 sémaphores pour synchroniser les threads. Il existe plusieurs types de mémoire selon la façon dont vous l'utilisez, mais elle sera plus longue, donc je vous l'expliquerai plus tard.
C'est presque comme ça. Les performances ne sont pas élevées car c'est pour mobile, mais je pense qu'il sera intéressant de jouer avec car vous pouvez obtenir le document complet, vous pouvez l'acheter pour quelques milliers de yens, et il est rare d'avoir un GPGPU autre que NVIDIA. Bien entendu, si vous faites une sorte de projet avec un smartphone équipé de Raspberry Pi ou VideoCore IV, j'apprécierais cette puissance de calcul.
PyVideoCore
Malheureusement, VideoCore IV n'a pas (probablement) d'environnement de développement GPGPU comme CUDA ou OpenCL, vous devez donc développer dans le langage d'assemblage pour QPU. En premier lieu, il n'y a ni langage ni assembleur. Les projets suivants ont été réalisés dans le passé, mais il semble qu'ils développent leurs propres assembleurs.
** PyVideoCore ** a essayé d'implémenter le langage d'assemblage en tant que DSL interne de Python pour le rendre un peu plus facile à écrire. Ce qui suit est un exemple qui ajoute simplement un vecteur flottant de longueur 16, mais vous pouvez écrire le code côté hôte et le code côté GPU dans un fichier et l'exécuter comme un script Python normal sans compilation.
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))
Le code d'assemblage a un décorateur appelé @ qpu
. Actuellement, il est nécessaire d'écrire un assemblage brut, mais le code GPU lui-même est une fonction normale, et comme chaque instruction est également une fonction ordinaire, il est possible de concevoir une bibliothèque de modèles fréquemment utilisés à l'aide des fonctions Python. pense.
Voici le référentiel. essayez-le.
Je pense prendre des benchmarks et construire des logiciels à partir de maintenant, donc je vais écrire à nouveau.
Recommended Posts