2016-04-19 11 views
2

ich einen Test geschrieben, mein Problem zu veranschaulichen, versuchen Sie den Code 16 Bytes zu einem keine-4-Byte-ausgerichteten Speicher zu kopieren, aber die dest wird automatischcuda Speicherkopie Kraft ausgerichtet

#include <cuda.h> 
#include <cuda_runtime.h> 
#include <stdio.h> 

__global__ 
void Copy128(char *dest,const char *src) 
{ 
    ((int*)dest)[0]=((int*)src)[0]; 
    ((int*)dest)[1]=((int*)src)[1]; 
    ((int*)dest)[2]=((int*)src)[2]; 
    ((int*)dest)[3]=((int*)src)[3]; 
} 
__global__ 
void fill_src(char *src) 
{ 
    for(int i=0; i<16; i++) 
     src[i] = i+1; // starts from 1 
} 

int main() 
{ 
    char* dest; 
    cudaMalloc(&dest, 17); 

    char* src; 
    cudaMalloc(&src, 16); 

    fill_src<<<1, 1>>>((char*)src); // fill some value for debugging 

    // copy to dest+1 which is not aligned to 4 
    Copy128<<<1, 1>>>(dest + 1, src); 

    getchar(); 
} 

modifizierte Debuggen den Code in VS2013 wie im Bild, ist der Zielspeicher 0x40A8000 , aber eigentlich ist es Kopien 0x40A8000 . enter image description here

Das Problem ist die dest würde automatisch geändert werden, wenn es nicht auf 4-Byte ausgerichtet ist. Und es wurde still modifiziert, ich verbrachte Stunden damit, diesen Fehler zu finden.

Ich weiß, es ist am besten, gut ausgerichteten Speicher zu verwenden, aber ich schreibe einige Rar-Dekomprimierungsprogramm, dekomprimiere einige Bytes und dann einige Bytes concat, es kann nicht immer ausgerichtet werden.

Ich glaube, ich würde uint64 in Funktion wie Copy256 verwenden. Ist das normale Verhalten, dass der Speicher kraftorientiert ist? Irgendwelche kompilierenden Flags, die diese Funktionalität ausschalten können? Oder sollte ich Bytes nacheinander kopieren?

Umwelt: CUDA 6.5, Win7-32bit, VS2013

+5

Wenn ich Ihren Beispielcode zum ausführen ich einen illegalen Schreibfehler im Copy128 Kernel erhalten, weil des nicht ausgerichteten Speicherzugriff, das ist genau das, was geschehen soll. Ich verstehe nicht, welchen Punkt Sie hier zu machen versuchen – talonmies

+4

Anders als auf x86-CPUs müssen alle Speicherzugriffe auf eine GPU natürlich ausgerichtet sein, das heißt, auf die Größe des Zugriffs, z. Der 4-Byte-Zugriff muss auf eine 4-Byte-Grenze ausgerichtet sein. Auf GPUs ist diese Ausrichtung für Speicherzugriffe für * funktionale Korrektheit * erforderlich, nicht nur für die Leistung wie bei x86. Dies wird in der CUDA-Dokumentation erwähnt. Bei fehlausgerichteten Kopien müssen Sie größere Objekte nicht Byte für Byte kopieren, sondern nur die schmalen Zugriffe für die Endfälle verwenden und für den Großteil der Übertragung breite Kopien verwenden. – njuffa

Antwort

4

- Ist das ein normales Verhalten, dass die Speicherkraft ausgerichtet ist? Yes: Zitat von here „Jede Adresse einer Variablen mit Wohnsitz im globalen Speicher oder zurückzugeführt, indem eine der Speicherzuweisungsroutinen vom Fahrer oder Laufzeit-API ist immer ausgerichtet auf mindestens 256 Bytes“.

Any Kompilieren Flags, die diese Funktionalität abschalten kann? Ich denke nicht, das ist wahrscheinlich Hardware bezogenen

Oder sollte ich Bytes nacheinander kopieren? Wenn Sie mit (sehr) unausgerichtetem Speicher arbeiten, ist dies die einzige Möglichkeit, um falsch ausgerichtete Speicher zu vermeiden (wie oben erwähnt). Sie sollten jedoch versuchen, (entweder zur Kompilierungszeit oder zur Laufzeit) zu erkennen, wenn Ihre Speicheroperationen ausgerichtet sind, und dann den breitesten Lade-/Speicher verwenden, den Sie zur Hand haben (int4 führt zu ldg-Anweisungen, die Ihnen einen besseren Weg geben) Bandbreite)