Rockchip · AI & Linux Hub

KI-Inferenz

RKNN Runtime C API V2.5.0 — Gerät, Kontext und Initialisierungsflags

RKNN Runtime C API V2.5.0 — Gerät, Kontext und Initialisierungsflags | Vollständige Parameter, Beispiele und Plattformgrenzen

· ArmSoM · 12 Min. Lesezeit

Plattform und Quelle

Dieser Artikel basiert auf dem RKNN-V2.5.0-PDF des Herstellers und gilt nur für die dort genannten Chips und Schnittstellen. Bei ArmSoM-Boards zuerst SoC, NPU-Treiber, Toolkit/Runtime, SDK/BSP und Kernelversion prüfen. Eine ArmSoM-Hardwareprüfung wurde nicht durchgeführt; Beispiele und Messwerte stammen aus der Quelle, nicht aus ArmSoM-Tests.

Seriennavigation

5. Funktionsreferenz

API-Funktionen

Funktionale Einteilung der RKNN-C-API:

Kategorie Beschreibung
5.1. Gerät und Kontext Laufzeitkontext initialisieren und auflösen; NPU-Kerne konfigurieren.
5.2. Abfragen Modellattribute, SDK-Version, Speicherbedarf und weitere Informationen abfragen.
5.3. Inferenz ausführen Eingaben setzen, Inferenz ausführen, Ausgaben abrufen und dynamische Formen einstellen.
5.4. Tensoren und Speicher Tensorspeicher zuweisen, freigeben, synchronisieren und benutzerdefinierten Speicher setzen.
5.5. Matrixmultiplikation Matrixmultiplikationskontext erstellen, Speicher und Quantisierungsparameter setzen, ausführen.
5.6. Benutzerdefinierte Operatoren Benutzerdefinierte Operatoren registrieren und Operatorattribute abrufen.

5.1. Gerät und Kontext

Laufzeitkontext initialisieren und auflösen; NPU-Kerne konfigurieren.

rknn_init

Die Initialisierungsfunktion rknn_init erstellt ein rknn_context-Objekt, lädt das RKNN-Modell und führt die durch Flags und rknn_init_extend festgelegte Initialisierung aus.

API rknn_init
Beschreibung Initialisiert den rknn-Kontext.
Parameter rknn_context *context: Zeiger auf das rknn_context-Objekt.
Parameter void *model: Binärdaten des RKNN-Modells oder dessen Pfad. Bei size>0 Binärdaten, bei size=0 Modellpfad.
Parameter uint32_t size: Größe des als Binärdaten übergebenen Modells; 0, wenn model einen Pfad enthält.
Parameter uint32_t flag: Initialisierungsflag; für das Standardverhalten auf 0 setzen.
Parameter rknn_init_extend: erweiterte Informationen für besondere Initialisierung. Die Quelle nennt diese deaktiviert und fordert NULL, verlangt beim Teilen von Gewichten jedoch einen Zeiger auf einen anderen rknn_context für ein anderes Modell. Beide Aussagen bleiben erhalten.
Rückgabe int: Fehlercode (siehe Statuscodes).

Codebeispiel:

rknn_context ctx;
int ret = rknn_init(&ctx, model_data, model_data_size, 0, NULL);

Die Initialisierungsflags werden nachfolgend erläutert:

RKNN_FLAG_PRIOR_HIGH: Hohe Kontextpriorität setzen.

RKNN_FLAG_PRIOR_MEDIUM: Mittlere Kontextpriorität setzen.

RKNN_FLAG_PRIOR_LOW: Niedrige Kontextpriorität setzen.

RKNN_FLAG_ASYNC_MASK: Asynchroner Modus. rknn_outputs_get liefert ohne langes Blockieren das Ergebnis des vorherigen Frames; dies kann die Bildrate bei einem Thread erhöhen, liefert aber nicht das aktuelle Frame-Ergebnis. Bei mehreren Threads ist dieser Modus nicht erforderlich.

RKNN_FLAG_COLLECT_PERF_MASK: ermöglicht die Abfrage der Laufzeit jeder Netzwerkschicht.

RKNN_FLAG_MEM_ALLOC_OUTSIDE: kennzeichnet, dass der Benutzer den Speicher für Modelleingaben, Ausgaben, Gewichte und Zwischentensoren vollständig selbst zuweist. Dies hat zwei Hauptzwecke:

1) Der Benutzer weist den gesamten Speicher zu, was die systemweite Speicherplanung erleichtert.

2) Zur Wiederverwendung von Speicher, besonders bei sehr knappem Speicher auf RV1106/RV1103/RV1106B/RV1103B/RK2118.

Angenommen, die Modelle A und B werden nacheinander ausgeführt. Dann lässt sich der Speicher ihrer Zwischentensoren wiederverwenden. Beispielcode:

rknn_context ctx_a, ctx_b;

rknn_init(&ctx_a, model_path_a, 0, RKNN_FLAG_MEM_ALLOC_OUTSIDE, NULL);
rknn_query(ctx_a, RKNN_QUERY_MEM_SIZE, &mem_size_a, sizeof(mem_size_a));

rknn_init(&ctx_b, model_path_b, 0, RKNN_FLAG_MEM_ALLOC_OUTSIDE, NULL);
rknn_query(ctx_b, RKNN_QUERY_MEM_SIZE, &mem_size_b, sizeof(mem_size_b));

max_internal_size = MAX(mem_size_a.total_internal_size, mem_size_b.total_internal_size);
internal_mem_max = rknn_create_mem(ctx_a, max_internal_size);

internal_mem_a = rknn_create_mem_from_fd(ctx_a, internal_mem_max->fd,
      internal_mem_max->virt_addr, mem_size_a.total_internal_size, 0);
rknn_set_internal_mem(ctx_a, internal_mem_a);

internal_mem_b = rknn_create_mem_from_fd(ctx_b, internal_mem_max->fd,
      internal_mem_max->virt_addr, mem_size_b.total_internal_size, 0);
rknn_set_internal_mem(ctx_b, internal_mem_b);

RKNN_FLAG_SHARE_WEIGHT_MEM: dient zur gemeinsamen Nutzung der Gewichte eines anderen Modells. Hauptzweck ist die Nachbildung variabler Eingabelängen; ab RKNPU Runtime 1.5.0 wird diese Funktion durch dynamische Formen ersetzt. Beispielsweise haben manche Sprachmodelle variable Eingabelängen, die NPU unterstützt diese jedoch nicht unmittelbar. Daher werden mehrere RKNN-Modelle unterschiedlicher Auflösung erzeugt. Nur eines enthält vollständige Gewichte, die anderen keine. Bei Initialisierung eines Modells ohne Gewichte erlaubt dieses Flag dem aktuellen Kontext, die Gewichte des vollständigen Modells mitzunutzen. Für zwei Modelle mit Auflösung A und B gilt folgender Ablauf:

1) Mit RKNN-Toolkit2 ein Modell mit Auflösung A erzeugen.

2) Ein Modell mit Auflösung B ohne Gewichte erzeugen: remove_weight in rknn.config() auf True setzen, um Modell B zu verkleinern.

3) Modell A auf dem Board normal initialisieren.

4) Modell B mit RKNN_FLAG_SHARE_WEIGHT_MEM initialisieren.

5) Weitere Schritte unverändert ausführen. Board-Codebeispiel:

rknn_context ctx_a, ctx_b;
rknn_init(&ctx_a, model_path_a, 0, 0, NULL);

rknn_init_extend extend;
extend.ctx = ctx_a;
rknn_init(&ctx_b, model_path_b, 0, RKNN_FLAG_SHARE_WEIGHT_MEM, &extend);

RKNN_FLAG_FENCE_IN_OUTSIDE: Fence-fd von außen übergeben.

RKNN_FLAG_FENCE_OUT_OUTSIDE: Internen Fence-fd abrufen.

RKNN_FLAG_COLLECT_MODEL_INFO_ONLY: initialisiert einen leeren Kontext. Darin lässt sich nur rknn_query zur Abfrage der Gesamtgrößen des Gewichtsspeichers und der Zwischentensoren aufrufen; Inferenz ist nicht möglich.

RKNN_FLAG_INTERNAL_ALLOC_OUTSIDE: Der Benutzer weist die Zwischentensoren des Modells zu. Dies wird häufig zur eigenen Verwaltung und Wiederverwendung des Zwischentensorspeichers mehrerer Modelle genutzt.

RKNN_FLAG_EXECUTE_FALLBACK_PRIOR_DEVICE_GPU: Alle von der NPU nicht unterstützten Schichten sollen bevorzugt auf der GPU laufen, ohne Garantie. Das tatsächliche Ausführungsgerät hängt von der Operatorunterstützung der Runtime ab.

RKNN_FLAG_ENABLE_SRAM: Zwischentensorspeicher wird nach Möglichkeit im SRAM zugewiesen.

RKNN_FLAG_SHARE_SRAM: Der aktuelle Kontext versucht, den SRAM-Adressraum eines anderen Kontexts mitzunutzen. Bei seiner Initialisierung muss RKNN_FLAG_ENABLE_SRAM aktiviert sein.

RKNN_FLAG_DISABLE_PROC_HIGH_PRIORITY: Der aktuelle Kontext verwendet die Standardprozesspriorität. Ohne dieses Flag beträgt der nice-Wert des Prozesses -19.

RKNN_FLAG_DISABLE_FLUSH_INPUT_MEM_CACHE: Die Runtime schreibt den Eingabetensor-Cache nicht zurück; der Benutzer muss dies vor rknn_run sicherstellen.

RKNN_FLAG_DISABLE_FLUSH_OUTPUT_MEM_CACHE: Die Runtime bereinigt den Ausgabetensor-Cache nicht aktiv. Direkter Benutzerzugriff auf output_mem->virt_addr kann dann Cache-Konsistenzprobleme verursachen. Vor der Nutzung von output_mem->virt_addr ist der Cache mit rknn_mem_sync(ctx, mem, RKNN_MEMORY_SYNC_FROM_DEVICE) zu aktualisieren. Das Flag wird typischerweise eingesetzt, wenn nicht die CPU, sondern etwa GPU oder RGA die NPU-Ausgabe liest.

RKNN_FLAG_MODEL_BUFFER_ZERO_COPY: Der an rknn_init übergebene Modellpuffer wurde durch rknn_create_mem oder rknn_create_mem2 zugewiesen. Die Runtime erstellt keine zusätzliche Pufferkopie und benötigt dadurch weniger Speicher. Der Benutzer muss den Modellspeicher bis zur Zerstörung des Kontexts gültig halten und danach freigeben. Bei der Initialisierung werden real_model_offset, real_model_size, model_buffer_fd und model_buffer_flags des Parameters rknn_init_extend von rknn_init anhand des von rknn_create_mem2 zurückgegebenen rknn_tensor_mem gesetzt.

RKNN_MEM_FLAG_ALLOC_NO_CONTEXT: erlaubt bei Speicherzuweisung über rknn_create_mem2 einen ctx-Wert von 0 oder NULL. So lässt sich vom NPU-Treiber zugewiesener Speicher bereits vor der Initialisierung eines Kontexts erhalten. Die zurückgegebene Speicherstruktur muss über rknn_destroy_mem freigegeben werden; dabei kann ein beliebiger Kontext übergeben werden. Beispielcode:

  rknn_tensor_mem* model_mem = rknn_create_mem2(ctx, model_size, RKNN_MEM_FLAG_ALLOC_NO_CONTEXT);
  memcpy(model_mem->virt_addr, model_data, model_size);
  rknn_init_extend init_ext;
  memset(&init_ext, 0, sizeof(rknn_init_extend));
  init_ext.real_model_offset = 0;
  init_ext.real_model_size = model_size;
  init_ext.model_buffer_fd = model_mem->fd;
  init_ext.model_buffer_flags = model_mem->flags;
  int ret = rknn_init(&ctx, model_mem->virt_addr, model_size, RKNN_FLAG_MODEL_BUFFER_ZERO_COPY,
&init_ext);

  // do rknn inference...

  rknn_destroy_mem(ctx, model_mem);
  rknn_destroy(ctx);

rknn_set_core_mask

Die Funktion legt die auszuführenden NPU-Kerne fest. Im beschriebenen Stand funktioniert sie nur auf RK3588 und RK3576. Bei einer Plattform mit einkerniger NPU wird ein Fehlercode zurückgegeben.

API rknn_set_core_mask
Beschreibung Legt die NPU-Kerne fest.
Parameter rknn_context context: rknn_context-Objekt.
Parameter rknn_core_mask core_mask: Auswahl der NPU-Kerne. RKNN_NPU_CORE_AUTO — automatische Auswahl eines freien Kerns; RKNN_NPU_CORE_0 — NPU0; RKNN_NPU_CORE_1 — NPU1; RKNN_NPU_CORE_2 — NPU2; RKNN_NPU_CORE_0_1 — NPU0 und NPU1 gleichzeitig; RKNN_NPU_CORE_0_1_2 — NPU0, NPU1 und NPU2 gleichzeitig; RKNN_NPU_CORE_ALL — alle NPU-Kerne der Plattform.
Rückgabe int: Fehlercode (siehe Statuscodes).
rknn_context ctx;
rknn_core_mask core_mask = RKNN_NPU_CORE_0;
int ret = rknn_set_core_mask(ctx, core_mask);

In den Mehrkernmodi RKNN_NPU_CORE_0_1 und RKNN_NPU_CORE_0_1_2 profitieren Conv, DepthwiseConvolution, Add, Concat, Relu, Clip, Relu6, ThresholdedRelu, Prelu und LeakyRelu von besserer Beschleunigung. Andere Operatoren laufen weiter auf Core0. Die Quelle kündigt Pool und ConvTranpose für spätere Updates an; dies ist keine Bestätigung ihrer aktuellen Implementierung.

rknn_set_batch_core_num

rknn_set_batch_core_num legt die Anzahl der NPU-Kerne für ein Multi-Batch-RKNN-Modell fest, das in RKNN-Toolkit2 mit rknn_batch_size größer als 1 exportiert wurde. Unterstützt werden nur RK3588 und RK3576.

API rknn_set_batch_core_num
Beschreibung Legt die NPU-Kernanzahl für ein Multi-Batch-RKNN-Modell fest.
Parameter rknn_context context: rknn_context-Objekt.
Parameter int core_num: Anzahl der auszuführenden Kerne.
Rückgabe int: Fehlercode (siehe Statuscodes).

Codebeispiel:

rknn_context ctx;
int ret = rknn_set_batch_core_num(ctx, 2);

rknn_dup_context

rknn_dup_context erstellt einen neuen Kontext für dasselbe Modell. Dies ermöglicht die Wiederverwendung der Modellgewichte bei Ausführung desselben Modells in mehreren Threads. Auf RV1106/RV1103/RV1106B/RV1103B/RK2118 nicht verfügbar.

API rknn_dup_context
Beschreibung Erstellt einen neuen Kontext desselben Modells zur Wiederverwendung der Gewichte.
Parameter rknn_context *context_in: Zeiger auf ein rknn_context-Objekt. Laut Quelle wird der Eingabekontext nach dem Aufruf initialisiert.
Parameter rknn_context *context_out: Zeiger auf ein rknn_context-Ausgabeobjekt mit den zurückgegebenen Informationen über das neu erstellte Objekt.
Rückgabe int: Fehlercode (siehe Statuscodes).

Codebeispiel:

rknn_context ctx_in;
rknn_context ctx_out;
int ret = rknn_dup_context(&ctx_in, &ctx_out);

rknn_destroy

Diese Funktion gibt rknn_context und zugehörige Ressourcen frei.

API rknn_destroy
Beschreibung Zerstört rknn_context und zugehörige Ressourcen.
Parameter rknn_context context: zu zerstörendes rknn_context-Objekt.
Rückgabe int: Fehlercode (siehe Statuscodes).

Codebeispiel:

rknn_context ctx;
int ret = rknn_destroy(ctx);

Quelle und redaktionelle Hinweise

Technische Kapitel sind nach Anwendung aufgeteilt. Code, Bezeichner und Parameter bleiben erhalten. Chinesisch folgt der chinesischen Quelle, Englisch, Russisch und Deutsch der englischen. Für Kapitel ohne Abbildungen wurden keine erfundenen Bilder hinzugefügt.

Hinweise zur Quelle: Kapitelnummern und Beispielausgaben bleiben erhalten; ältere SDK-Versionen in Protokollen sind nicht die aktuelle Dokumentversion. Die Runtime-Quelle springt von Kapitel 3 zu 5 und wiederholt Abfragenummern. Die rknn_init-Tabelle bezeichnet extend als deaktiviert, spätere Typen beschreiben jedoch user_key und gemeinsame Gewichte. Der Text zur nativen dynamischen Ausgabe nennt RKNN_QUERY_CURRENT_OUTPUT_ATTR, das Beispiel RKNN_QUERY_CURRENT_NATIVE_OUTPUT_ATTR. Einige native NHWC/NC1HWC2-Beschreibungen verwechseln Ein- und Ausgabe. Mit tatsächlichen V2.5.0-Headern und Ziel-SDK abgleichen; das Verhalten wurde nicht getestet. Der RK2118-Verweis heißt im Original RKNN3_RK2118_Quick_Start.pdf, im aktuellen Verzeichnis liegt eine RKNN2-Kurzanleitung.

RKNN-Toolkit2 · ArmSoM documentation

Dieses Thema entdecken → · Lernpfade →