Frage

Ich habe ein ARM NEON Cortex-A8-basierten Prozessor Ziel. Ich war die Optimierung meinen Code durch die Verwendung von NEON machen. Aber wenn ich meinen Code kompilieren bekomme ich diese seltsamen Fehler. Sie wissen nicht, wie dieses Problem zu beheben.

Ich versuche, den folgenden Code (Teil 1) mit Code Sourcery (PART2) auf meinem Host zu kompilieren. Und ich bekomme diesen seltsamen Fehler (PART3). Mache ich etwas falsch hier? Kann jemand anderes dieses kompiliert und sehen, ob sie auch den gleichen Übersetzungsfehler erhalten?

Das seltsame Teil, in dem Code, wenn ich den else if(step_size == 4) Teil des Codes einen Kommentar, dann verschwindet der Fehler. Doch leider meine Optimierung ist nicht vollständig mit aus es, so dass ich es haben muss.

Zuerst dachte ich, sein das Problem mit CodeSourcey Compiler (auf meinem Rechner), so dass ich das Programm auf meinem Ziel kompilierte direkt (Mein Ziel läuft auf Ubuntu). Früher habe ich gcc dort und noch einmal, ich den gleichen Fehler, und wenn ich den else if(step_size == 4) Teil kommentieren, dann der Fehler verschwindet.

Hilfe


TEIL 1

#include<stdio.h>
#include"arm_neon.h"

#define IMAGE_HEIGHT 480
#define IMAGE_WIDTH  640

float32_t integral_image[IMAGE_HEIGHT][IMAGE_WIDTH];

float32x4_t box_area_compute3(int, int , int , int , unsigned int , float);

inline int min(int, int);

int main()
{

 box_area_compute3(1, 1, 4, 4, 2, 0);

 return 0;
}

float32x4_t box_area_compute3(int row, int col, int num_rows, int num_cols, unsigned int step_size, float three)
{
 unsigned int height = IMAGE_HEIGHT;
 unsigned int width = IMAGE_WIDTH;

 int temp_row = row + num_rows;
 int temp_col = col + num_cols;

 int r1 = (min(row, height))- 1 ;
 int r2 = (min(temp_row, height)) - 1;

 int c1 = (min(col, width)) - 1;
 int c2 = (min(temp_col, width)) - 1;

 float32x4_t v128_areas;

 if(step_size == 2)
 {
  float32x4x2_t top_left, top_right, bottom_left, bottom_right;
  top_left    = vld2q_f32((float32_t *)integral_image[r1] + c1);
  top_right   = vld2q_f32((float32_t *)integral_image[r1] + c2);
  bottom_left  = vld2q_f32((float32_t *)integral_image[r2] + c1);
  bottom_right  = vld2q_f32((float32_t *)integral_image[r2] + c2);

  v128_areas = vsubq_f32(vsubq_f32(vaddq_f32(top_left.val[0], bottom_right.val[0]), top_right.val[0]), bottom_left.val[0]);


 }
 else if(step_size == 4)
 {
  float32x4x4_t top_left, top_right, bottom_left, bottom_right;
  top_left   = vld4q_f32((float32_t *)integral_image[r1] + c1);
  top_right   = vld4q_f32((float32_t *)integral_image[r1] + c2);
  bottom_left  = vld4q_f32((float32_t *)integral_image[r2] + c1);
  bottom_right  = vld4q_f32((float32_t *)integral_image[r2] + c2);

  v128_areas = vsubq_f32(vsubq_f32(vaddq_f32(top_left.val[0], bottom_right.val[0]), top_right.val[0]), bottom_left.val[0]);

 }

 if(three == 3.0)
  v128_areas = vmulq_n_f32(v128_areas, three);

 return v128_areas;

}

inline int min(int X, int Y)
{
 return (X < Y ? X : Y);
}

TEIL 2

arm-none-linux-gnueabi-gcc -O0 -g3 -Wall -c -fmessage-length=0 -fcommon -MMD -MP -MF"main.d" -MT"main.d" -mcpu=cortex-a8 -marm -mfloat-abi=hard -mfpu=neon-vfpv4 -o"main.o" "../main.c"

TEIL 3

../main.c: In function 'box_area_compute3':
../main.c:65: error: unable to find a register to spill in class 'GENERAL_REGS'
../main.c:65: error: this is the insn:
(insn 226 225 227 5 c:\program files\codesourcery\sourcery g++\bin\../lib/gcc/arm-none-linux-gnueabi/4.4.1/include/arm_neon.h:9863 (parallel [
           (set (reg:XI 148 [ D.17028 ])
               (unspec:XI [
                       (mem:XI (reg:SI 3 r3 [301]) [0 S64 A64])
                       (reg:XI 148 [ D.17028 ])
                       (unspec:V4SF [
                               (const_int 0 [0x0])
                           ] 191)
                   ] 111))
           (set (reg:SI 3 r3 [301])
               (plus:SI (reg:SI 3 r3 [301])
                   (const_int 32 [0x20])))
       ]) 1605 {neon_vld4qav4sf} (nil))
../main.c:65: confused by earlier errors, bailing out
cs-make: *** [main.o] Error 1
War es hilfreich?

Lösung 2

Nun, ich hatte den Kodex Sourcery über dieses Problem in Kontakt gebracht und sie haben dies in GCC-Compiler als Fehler betrachtet. Also schrieb ich die do_it4 () {.....} function in der Montage statt teh intrinsics verwenden. Jetzt funktioniert es gut!

Andere Tipps

Das kann ich nicht testen, weil ich für die Werkzeugkette nicht habe, aber diese Art von Fehler kann oft durch Umformulierung des Code ein wenig gearbeitet wird um. Generell sollte dies nicht passieren, und es sollte als Fehler gemeldet werden, aber Sie verwenden prozessorspezifische Funktionalität, die wahrscheinlich weniger gut getestet und poliert als der Rest des Compilers.

Da es sich um ein Register spill Fehler und Sie haben mehrere Zeiger beteiligt ich höchst verdächtig, dass der Compiler versucht werden kann, mehr Daten in die Register zu laden, als es aus Angst muss, dass es möglicherweise einige Aliasing sein geht (was wahrscheinlich geschieht nicht wirklich). Im Folgenden werde ich mit der Möglichkeit, dass auch tun, ein paar andere Dinge, die vermindern kann die Komplexität des Codes aus der Compiler Perspektive befassen wird (obwohl es nicht so ist der Fall aussehen könnte).

#include<stdio.h>
#include"arm_neon.h"

#define IMAGE_HEIGHT 480
#define IMAGE_WIDTH  640

float32_t integral_image[IMAGE_HEIGHT][IMAGE_WIDTH];

float32x4_t box_area_compute3(int, int , int , int , unsigned int , float);

inline int min(int, int);

int main()
{

 box_area_compute3(1, 1, 4, 4, 2, 0);

 return 0;
}

/* By putting these in separate functions the compiler will initially
 * think about them by themselves, without the complications of the
 * surrounding code.  This may give it the abiltiy to optimise the
 * code somewhat before trying to inline it.
 * This may also serve to make it more obvious to the compiler that
 * the local variables are dead after their use (since they are
 * dead after the call returns, and that the lifetimes of some variable
 * cannot actually overlap (hopefully reducing the register needs).
 */
static inline float32x4_t do_it2(float32_t *tl, float32_t *tr, float32_t *bl, float32_t * br) {
    float32x4x2_t top_left, top_right, bottom_left, bottom_right;
    float32x4_t A, B;

    top_left = vld2q_f32(tl);
    top_right = vld2q_f32(tr);
    bottom_left = vld2q_f32(bl);
    bottom_right = vld2q_f32(br);

    /* By spreading this across several statements I have created several
     * additional sequence points.  The compiler does not think that it
     * has to dereference all of the pointers before doing any of the
     * computations.... maybe. */
    A = vaddq_f32(*top_left.val, *bottom_right.val);
    B = vsubq_f32(A, *top_right.val);
    return vsubq_f32(B, *bottom_left);
}

static inline float32x4_t do_it4(float32_t *tl, float32_t *tr, float32_t *bl, float32_t * br) {
    float32x4x4_t top_left, top_right, bottom_left, bottom_right;
    float32x4_t A, B;

    top_left = vld4q_f32(tl);
    top_right = vld4q_f32(tr);
    bottom_left = vld4q_f32(bl);
    bottom_right = vld4q_f32(br);

    A = vaddq_f32(*top_left.val, *bottom_right.val);
    B = vsubq_f32(A, *top_right.val);
    return vsubq_f32(B, *bottom_left);
}

float32x4_t box_area_compute3(int row, int col, int num_rows, int num_cols, unsigned int step_size, float three)
{
 unsigned int height = IMAGE_HEIGHT;
 unsigned int width = IMAGE_WIDTH;

 int temp_row = row + num_rows;
 int temp_col = col + num_cols;

 int r1 = (min(row, height))- 1 ;
 int r2 = (min(temp_row, height)) - 1;

 int c1 = (min(col, width)) - 1;
 int c2 = (min(temp_col, width)) - 1;

 float32x4_t v128_areas;

     float32_t *tl = (float32_t *)integral_image[r1] + c1;
 float32_t *tr = (float32_t *)integral_image[r1] + c2;
 float32_t *bl = (float32_t *)integral_image[r2] + c1;
 float32_t *br = (float32_t *)integral_image[r2] + c2;


 switch (step_size) {
    case 2:
      v128_areas = do_it2(tl, tr, bl, br);
      break;

 case 4:
      v128_areas = do_it4(tl, tr, bl, br);
      break;
 }

 if(three == 3.0)
  v128_areas = vmulq_n_f32(v128_areas, three);

 return v128_areas;

}

inline int min(int X, int Y)
{
 return (X < Y ? X : Y);
}

Ich hoffe, dass dies hilft, und dass ich keine Fehler eingeführt haben.

Die Zeile:

float32x4x4_t top_left, top_right, bottom_left, bottom_right;

verwendet alle 16 q Register! Es ist nicht allzu überraschend, dass der Compiler diese nicht verarbeiten kann. Sie wahrscheinlich dies könnte durch Umschreiben fixiert weniger Register zu verwenden.

ARM NEON Cortex-A8 haben vfpv3 Unterstützung, Cortex-A5 haben vfpv4 und neon2 Unterstützung, (wie: Wenn Sie -mfloat-abi = verwenden hart Sie Fähigkeit zu emulieren in Software überspringen Anweisungen fehlen, so dass Sie nicht Code generieren können, die würde für vfpv4 optimiert werden, sondern auf vfpv3 mit Software-Emulation)

liefe
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top