2016-04-30 11 views
0

Ich habe versucht, meinen älteren Code schneller laufen zu lassen, als ich entdeckte, dass der RPi 2 Prozessor NEON Befehle unterstützt. Also schrieb ich diesen Code:Raspberry Pi 2 NEON Inline-Montageanleitung funktioniert nicht

__asm__ __volatile__(
    "vld1.8 {%%d2, %%d3}, [%1];" 
    "vld1.8 {%%d4, %%d5}, [%2];" 
    "vaba.u8 %%q0, %%q1, %%q2;" 
    "vst1.64 %%d0, [%0];" 
    : "=r" (address_sad_intermediary) 
    : "r" (address_big_pic), "r" (address_small_pic) 
    : 
); 

Dann in C die Haupt traurig Variable mit sad_intermediary summiert.

Das Hauptziel ist, die Summe der absoluten Differenzen zu berechnen, also lade ich 16 B von big_pic in q1 Register, 16 B von small_pic in q2 Register, berechne die SAD in q0 und lade dann die unteren 8 B von q0 in die Zwischenvariable. Das Problem ist, dass die resultierende Traurigkeit Null ist.

Ich benutze GCC 4.9.2 mit -std = c99 -pthread O3 -Im -Wall -march = ARMv7-a -mfpu = neon-vfpv4 -mfloat-abi = hart Optionen.

Haben Sie Probleme mit dem Code? Vielen Dank.

Antwort

1

Sie laden nie etwas in q0, also addiert die vaba die absolute Differenz zu einem nicht initialisierten Register. Es sieht auch so aus, als würden Sie nicht deklarieren, welche Register Sie ändern.

Aber ich weiß nicht, ob das die Ursache für Ihr Problem ist, weil ich mit der Inline-Montage nicht allzu praktisch bin. Sie sollten wahrscheinlich nicht Inline-Assembly für so etwas verwenden. Wenn Sie intrinsics verwenden, hat der Compiler eine bessere Möglichkeit, den Code zu optimieren. Etwas wie folgt aus:

#include <arm_neon.h> 

... 
uint8x8_t s = vld1_u8(address_sad_intermediary); 
s = vaba_u8(s, vld1_u8(address_big_pic), vld1_u8(address_small_pic)); 
vst1_u8(address_sad_intermediary, s); 

(beachten Sie, dass dieser Code nur mit acht Bytes arbeitet, weil man nur acht Bytes im Code speichern)

+0

Aber warum bin ich nicht nichts zum q0 Laden? In diesem [Dokument, p58] (https://people.xiph.org/~tterribe/daala/neon_tutorial.pdf) können Sie sehen, dass das Ergebnis im ersten Register gespeichert wird, in meinem Fall q0. Ich wollte nicht intrinsics verwenden, weil ich gelesen habe, dass die Leistung nicht ideal mit ihnen ist. –

+0

Die Leistung kann bei Inline-Montage schlechter sein. Intrinsics Performance war historisch schrecklich, aber gcc-6.1 ist jetzt verfügbar, und das und der moderne Clang machen beide einen vernünftigen Job. Solange der Code einfach ist, sollten sie nicht durcheinander kommen, und sie werden Pipelines planen, ohne dass Sie darüber nachdenken müssen. – sh1

+0

'vaba' liest von q0 und addiert dazu die absolute Differenz von q1 und q2. Sie müssen etwas in q0 haben, bevor Sie den Vorgang ausführen können, sonst erhalten Sie ein Nonsense-Ergebnis. – sh1