4 Stimmen

SIMD und dynamische Speicherzuweisung

Möglicher Duplikat:
SSE, Intrinsiken und Ausrichtung

Ich bin neu in der SIMD-Programmierung, also verzeihen Sie mir bitte, wenn ich eine offensichtliche Frage stelle.

Ich habe ein wenig experimentiert und bin zu dem Punkt gekommen, an dem ich einen SIMD-Wert in einer dynamisch allokierten Struktur speichern möchte.

Hier ist der Code:

struct SimdTest
{
    __m128      m_simdVal;

    void setZero()
    {
        __m128 tmp = _mm_setzero_ps(); 
        m_simdVal = tmp; // <<--- CRASH ---
    }
};

TEST( Plane, dynamischAllokiertesPlane )
{
    SimdTest* test = new SimdTest();

    test->setZero();

    delete test;
}

Wenn die mit CRASH kommentierte Methode ausgeführt wird, stürzt der Code mit der folgenden Ausnahme ab:

Unhandled exception at 0x775315de in test-core.exe: 0xC0000005: Zugriffsverletzung beim Lesen der Adresse 0x00000000

Könnte mir bitte jemand erklären, warum die Zuweisungsbetriebung fehlschlägt und wie SIMD-Objekte dynamisch allokiert werden müssen, damit sie einwandfrei funktionieren?

Ich muss hinzufügen, dass wenn ich ein SimdTest-Objekt statisch instanziiere und die setZero-Methode aufrufe, alles reibungslos funktioniert.

Danke, Paksas

5voto

Hans Passant Punkte 894572

Es stirbt, weil die Struktur falsch ausgerichtet ist. Der CRT-Zuweiser verspricht nur eine Ausrichtung von 8, hier sind 16 erforderlich. Sie müssen _aligned_malloc() in MSVC verwenden, um ordnungsgemäß ausgerichteten heap-allocated-Speicher zu erhalten.

Zwei Möglichkeiten, es zu lösen. Da es sich um eine POD-Struktur handelt, könnten Sie einfach umwandeln:

#include 
...
    SimdTest* test = (SimdTest*)_aligned_malloc(sizeof SimdTest, 16);
    test->setZero();
    _aligned_free(test);

Oder Sie könnten die new/delete-Operatoren für die Struktur überschreiben:

struct SimdTest
{
    void* operator new(size_t size) { return _aligned_malloc(size, 16); }
    void operator delete(void* mem) { return _aligned_free(mem); }
    // etc..
};

-1voto

Ivan0x32 Punkte 413

MSDN gibt an, dass die _m128 automatisch auf 16 Bytes ausgerichtet sind, nicht __m128, sondern _m128. Aber so oder so denke ich, dass die anderen richtig liegen, da ich mich erinnere, dass es zwei Arten von Bewegungsanweisungen gibt, eine für ausgerichtete movAps und eine für nicht ausgerichtet movUps. Ersteres erfordert eine 16B-Ausrichtung und das andere nicht. Weiß nicht, ob der Compiler in der Lage ist, beide zu verwenden, aber ich habe diese _m128-Art ausprobiert.

Eigentlich gibt es dafür einen speziellen Typ: _M128A.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X