Es ist endlich ein langer Weg und die Vorbereitungen sind abgeschlossen. Bewegen wir die Faltungsschaltung mit Ultra96V2-Karte!
Die folgende Datei wurde zuletzt erstellt (Tutorial AI Edge Contest (Implementierungswettbewerb) [9: HW-Synthese zum Generieren von Bitstream]) Muss.
Diese Dateien werden im 3. Tutorial (AI Edge Contest (Implementierungswettbewerb) [3: Inferenzausführung auf Ultra96-Board-CPU] beschrieben. Platzieren Sie es in / home / xylinx / pynq / Overlays / Base
auf der Ultra96 V2-Platine.
Auch den Prüfstand habe ich bisher benutzt
Platzieren Sie in / home / xylinx / data
.
Notizbuch zur Steuerung der Hardware ist ein Tutorial-Repository (https://girak_ Es befindet sich in blob / master / Inference_PYNQ_1
). Bitte klonen und platzieren Sie es in Ihrem Ultra96 V2-Home / home / xylinx
. Später wird es mit dem Ultra96 V2 Jupyter Notebook geladen.
Stellen Sie über Ihren Browser eine Verbindung zum Ultra96 V2 Jupyter Notebook her. Bitte beziehen Sie sich auf Teil 3.
Klicken Sie auf Hochladen, um das Notizbuch zu laden und auszuführen (ultra96v2_pynq_convolution_layer0.ipynb
). Wenn Sie danach von oben ausführen, werden die Vorbereitung, die Inferenzausführung (aber langsam) und die Inferenz auf der CPU zum Vergleich ausgeführt.
Im Folgenden werde ich mich auf die Hauptpunkte konzentrieren.
ultra96v2_pynq_convolution_layer0.ipynb
from pynq import Overlay
import pynq
overlay = Overlay('/home/xilinx/pynq/overlays/base/pynq_ultra96_conv_l0_r1.bit')
dir(overlay)
PYNQ abstrahiert die Hardware mit dem Konzept der Überlagerung. Wie Sie anhand der Anzeige sehen können, werden einige Kernnamen (kernel_0 oder axi_dma_0) angezeigt, die in der vorherigen IP-Verbindung verwendet wurden. Greifen Sie darauf zu und führen Sie Operationen aus.
ultra96v2_pynq_convolution_layer0.ipynb
registers = overlay.kernel_0.register_map
Sie können Ihren IP-Core beispielsweise mit Python steuern, indem Sie auf register_map zugreifen. Dieses Mal wird der AXI-Stream durch das Pragma angegeben, so dass die Bedienung einfach ist! Dies ist großartig (für alle, die AXI-Busse in RTL geschrieben haben).
Obwohl es sich um eine DMA-Einstellung handelt,
ultra96v2_pynq_convolution_layer0.ipynb
import pynq.lib.dma
dma = overlay.axi_dma_0
Und greifen Sie auf das Overlay zu
ultra96v2_pynq_convolution_layer0.ipynb
from pynq import Xlnk
inimg_size = 416*11*3
outfmap_size = 102*64+1
xlnk = Xlnk()
send_buf = xlnk.cma_array(shape=(inimg_size),dtype=np.int32)
recv_buf = xlnk.cma_array(shape=(outfmap_size),dtype=np.int32)
Und Xlnk ()
(ein Wrapper für DMA Control Middleware von Xilinx), ich habe das Array gesichert. Einfacher Sieg.
Hardware-Datenübertragung und -empfang
ultra96v2_pynq_convolution_layer0.ipynb
%%time
for line in range(102):
# load input image
for i in range(11):
inimg_buf[i] = inimg[i+line*4]
tmp = inimg_buf.copy().transpose((2,0,1)).reshape(-1,) # CH,Y,X
send_buf[0:inimg_size] = tmp[0:inimg_size]
# activate DMA
registers.CTRL.AP_START = 1
# DMA access
dma.sendchannel.transfer(send_buf)
dma.recvchannel.transfer(recv_buf)
# wait DMA
dma.sendchannel.wait()
dma.recvchannel.wait()
# store output buffer
tmp2 = recv_buf[0:outfmap_size - 1]
tmp2 = tmp2.reshape((64,102)) # CH, X
outfmap_buf[line] = tmp2
Übergeben Sie das numpy-Array (in diesem Fall inimg) und setzen Sie das Übertragungsstartregister auf ON (AP_START
). Übergeben Sie danach den Puffer an "Übertragung" und warten Sie, bis die Übertragung (dh die Verarbeitung der Faltungsoperation) abgeschlossen ist ("Warten"). Danach übergeben Sie die entsprechenden Daten an das Numpy-Array und Sie sind fertig. Wiederholen Sie dies für die Ausgabezeile.
Ich habe die Zeit mit "%% time" gemessen. Auf diese Weise können Sie einen externen Befehl in Jupyter Notebook aufrufen. Und welches
CPU times: user 22.5 s, sys: 6.85 ms, total: 22.5 s
Wall time: 22.5 s
Langsam. .. .. Immerhin war die Schätzung von 22 Sekunden und HLS genau. .. .. Wir überprüfen auch danach. Bitte bewegen Sie es und überprüfen Sie, ob die Hardware ordnungsgemäß funktioniert.
Übrigens sollte Pytorch installiert sein, also überprüfen wir die CPU-Inferenzzeit.
ultra96v2_pynq_convolution_layer0.ipynb
import torch
x = torch.randn(1,3,416,416)
conv = torch.nn.Conv2d(in_channels=3, out_channels=64, kernel_size=11,stride=4,bias=False)
y = conv(x)
CPU times: user 259 ms, sys: 7.96 ms, total: 267 ms
Wall time: 93.2 ms
Eh, ungefähr 100 mal schneller. .. .. Das ist Dosun. (Das ist durchaus üblich> FPGA-Design)
Also habe ich alle Schritte ausprobiert, um Pytorch zu lernen → Software-Design → Hardware-Design → tatsächlich mit FPGA zu arbeiten, aber das Ergebnis war enttäuschend. .. Ich denke, Sie können verstehen, wie hoch die Hürden für das Hardware-Design sind, geschweige denn für tiefes Lernen.
Bei dieser Geschwindigkeit ist es nicht gut genug, also lasst uns unser Bestes geben, um es schneller zu machen. Also wird es noch eine Weile dauern.
Recommended Posts