Frage

Im Moment habe ich den folgenden Code:

float a[4] = { 10, 20, 30, 40 };
float b[4] = { 0.1, 0.1, 0.1, 0.1 };
asm volatile("movups (%0), %%xmm0\n\t"
             "mulps (%1), %%xmm0\n\t"             
             "movups %%xmm0, (%1)"             
             :: "r" (a), "r" (b));

Ich habe zunächst einmal ein paar Fragen:

(1), wenn ich die Arrays auf 16-Byte-Grenzen auszurichten, würde es funktioniert auch? Da die Arrays auf dem Stack zugeordnet sind, ist es wahr, dass sie Ausrichtung nahezu unmöglich ist?

sehen die gewählte Antwort für diesen Beitrag: Sind stapeln Variablen vom GCC __attribute __ ausgerichtet ((ausgerichtet (x)) )?

(2) Kann der Code überhaupt Refactoring wird, um es effizienter? Was passiert, wenn ich beide Schwimmer-Arrays in Register setzen, anstatt nur ein?

Danke

War es hilfreich?

Lösung

  

Wenn ich die Arrays auf 16-Byte-Grenzen auszurichten, würde es funktioniert auch? Da die Arrays auf dem Stack zugeordnet sind, ist es wahr, dass sie Ausrichtung nahezu unmöglich ist?

Es ist erforderlich, dass die Ausrichtung auf dem Stapel funktioniert. Sonst wäre intrinsics nicht funktionieren. Ich würde vermuten, die Post, den Sie mit dem exorbitanten Wert, den er für den Ausrichtungswert ausgewählt zu tun hatte, zitiert.

2:

Nein, es soll keinen Unterschied in der Leistung sein. Sehen Sie dieses Website für den Befehl Timings von mehreren Prozessoren rel="nofollow.


Wie Ausrichtung von Stack-Variablen funktioniert:

push    ebp
mov ebp, esp
and esp, -16                ; fffffff0H
sub esp, 200                ; 000000c8H

Die und richtet sich die zu 16 Byte des Stapels beginnen.

Andere Tipps

Schreiben Sie es in C, verwenden Sie

gcc -S -mssse3

Wenn Sie eine ziemlich neue Version von gcc.

  

(1), wenn ich die Arrays auf 16-Byte-Grenzen auszurichten, würde es funktioniert auch? Da die Arrays auf dem Stack zugeordnet sind, ist es wahr, dass sie Ausrichtung nahezu unmöglich ist?

Nein, es ist ganz einfach, den Stapelzeiger mit and auszurichten:

and esp, 0xFFFFFFF0 ; aligned on a 16-byte boundary

Aber Sie sollten verwenden, was GCC bietet, wie zum Beispiel eines 16 Byte-Typen oder __attribute__ zu Ausrichtung anpassen.

Bieten GCC Unterstützung für den __m128 Datentyp? Wenn ja, das ist die beste Plan, einen 16-Byte-ausgerichteten Datentypen für die Gewährleistung. Dennoch gibt es __attribute__((aligned(16))) für Dinge ausrichten. Definieren Sie Ihre Arrays wie folgt

float a[4] __attribute__((aligned(16))) = { 10, 20, 30, 40 };
float b[4] __attribute__((aligned(16))) = { 0.1, 0.1, 0.1, 0.1 };

und dann MOVAPS verwendet stattdessen:)

intrinsische Verwendung ist viel schneller vor allem mit der Optimierung. Ich schrieb einfachen Test und vergleichen beide Version (asm und intrinsisch)

unsigned long long time1;
__m128 a1,b1;


a1=_mm_set_ps(10, 20,30,40);
b1=_mm_set_ps(0.1, 0.1, 0.1, 0.1);
float a[4] = { 10, 20, 30, 40 };
float b[4] = { 0.1, 0.1, 0.1, 0.1 };

time1=__rdtsc();
a1=_mm_mul_ps(a1,b1);
time1=__rdtsc() - time1 ;
printf("Time: %llu\n",time1);


time1=__rdtsc();
asm volatile("movups (%0), %%xmm0\n\t"
                 "mulps (%1), %%xmm0\n\t"
                 "movups %%xmm0, (%1)"
                 :: "r" (a), "r" (b));
time1=__rdtsc() - time1 ;
printf("Time: %llu\n",time1);

Intrinsic Version 50-60 Prozessor Zeitstempel Asm Version ~ 1000 proc Zeitstempel

Sie können es auf Ihrem Rechner testen

Über Refactoring. Sie können intrinsische verwenden. Beispiel:

#include <emmintrin.h>

int main(void)
{
    __m128 a1,b1;

    a1=_mm_set_ps(10, 20,30,40);
    b1=_mm_set_ps(0.1, 0.1, 0.1, 0.1);

    a1=_mm_mul_ps(a1,b1);

    return 0;
}

Mit Optimierung gcc (-O2, -O3) es schneller arbeiten dann asm sein kann.

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