2016-04-19 4 views
2

я написал тест, чтобы проиллюстрировать мою проблему, код попытке скопировать 16 байт на память ни один-4-байт-выровнены, но Dest автоматически изменяетсяCUDA копия памяти сила выровнен

#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(); 
} 

Отладка кода в VS2013, как на изображении, целевая память 0x40A8000 , но на самом деле она копирует в 0x40A8000 . enter image description here

Проблема заключается в Dest будет изменен автоматически, если оно не совпадает с 4 байта. И он модифицирован молча, я потратил несколько часов, чтобы найти эту ошибку.

Я знаю, что лучше использовать хорошо выровненную память, но я пишу какую-то программу декомпрессии rar, распаковываю несколько байтов, а затем конкатбайты некоторых байтов, ее нельзя всегда выровнять.

У меня есть функция uint64 в функции типа Copy256. Является ли это обычное поведение тем, что память выровнена по силе? Любые скомпилированные флаги, которые могут отключить эту функцию? Или я должен копировать байты один за другим?

Окружающая среда: CUDA 6.5, Win7-32bit, VS2013

+5

Когда я запускаю ваш пример кода, я получаю ошибку незаконной записи в ядре Copy128 из-за нерационального доступа к памяти, что и должно произойти. Я не понимаю, что вы пытаетесь сделать здесь – talonmies

+4

За исключением процессоров x86, все обращения к памяти на графическом процессоре должны быть естественно выровнены, то есть выровнены по размеру доступа, например. 4-байтовый доступ должен быть выровнен с 4-байтной границей. Таким образом, на графических процессорах это выравнивание для доступа к памяти необходимо для * функциональной корректности *, а не только для производительности, как на x86. Это упоминается в документации CUDA. Для несогласованных копий вам не нужно копировать более крупные объекты побайтно, просто используйте узкие обращения для конечных случаев и используйте большие копии для большей части передачи. – njuffa

ответ

4

- Это нормальное поведение, что память сила выровнены? Да: Цитируется по here: «Любой адрес переменной, находящейся в глобальной памяти или возвращаемой одной из подпрограмм выделения памяти из драйвера или API времени выполнения, всегда выровнен по крайней мере до 256 байтов».

Любые компиляционные флаги, которые могут отключить эту функцию? Я думаю, нет, это, вероятно, связано с оборудованием

Или мне нужно копировать байты один за другим? Если вы имеете дело с (очень) неизмененной памятью, это ваш единственный вариант, чтобы избежать несогласованных магазинов (как указано выше). Тем не менее, вы должны попытаться обнаружить (во время компиляции или во время выполнения), когда операции с памятью выровнены, а затем использовать самую большую нагрузку/хранилище, которое у вас есть (int4 приводит к инструкциям ldg, что даст вам лучший способ полоса пропускания)