2013-03-13 4 views
0

Я пытаюсь выяснить, почему cudaMemcpyToSymbol не работает для меня. (Но cudaMemcpy делает.)cudaMemcpyToSymbol vs cudaMemcpy

// symbols: 
__constant__ float flt[480]; // 1920 bytes 
__constant__ int ints[160]; // 640 bytes 

// func code follows: 
float* pFlts; 
cudaMalloc((void**)&pFlts, 1920+640); // chunk of gpu mem (floats & ints) 

// This does NOT work properly: 
cudaMemcpyToSymbol(flt,pFlts,1920,0,cudaMemcpyDeviceToDevice); // first copy 
cudaMemcpyToSymbol(ints,pFlts,640,1920,cudaMemcpyDeviceToDevice); // second copy 

Вторая копия громя содержимое первой копии (ВТФ), а второй экземпляр не бывает. (Если я удалю вторую копию, первый экземпляр работает отлично.)

Результаты:

GpuDumpFloatMemory<<<1,1>>>(0x500500000, 13, 320) TotThrds=1 ** Source of 1st copy 
    0x500500500: float[320]= 1.000 
    0x500500504: float[321]= 0.866 
    0x500500508: float[322]= 0.500 
    0x50050050c: float[323]= -0.000 
    0x500500510: float[324]= -0.500 
    0x500500514: float[325]= -0.866 
    0x500500518: float[326]= -1.000 
    0x50050051c: float[327]= -0.866 
    0x500500520: float[328]= -0.500 
    0x500500524: float[329]= 0.000 
    0x500500528: float[330]= 0.500 
    0x50050052c: float[331]= 0.866 
    0x500500530: float[332]= 1.000 
    GpuDumpFloatMemory<<<1,1>>>(0x500100a98, 13, 320) TotThrds=1  ** Dest of 1st copy 
    0x500100f98: float[320]= 0.000 
    0x500100f9c: float[321]= 0.500 
    0x500100fa0: float[322]= 0.866 
    0x500100fa4: float[323]= 1.000 
    0x500100fa8: float[324]= 0.866 
    0x500100fac: float[325]= 0.500 
    0x500100fb0: float[326]= -0.000 
    0x500100fb4: float[327]= -0.500 
    0x500100fb8: float[328]= -0.866 
    0x500100fbc: float[329]= -1.000 
    0x500100fc0: float[330]= -0.866 
    0x500100fc4: float[331]= -0.500 
    0x500100fc8: float[332]= 0.000 
    GpuDumpIntMemory<<<1,1>>>(0x500500780, 13, 0) TotThrds=1  ** Source of 2nd copy 
    0x500500780: int[0]= 1 
    0x500500784: int[1]= 1 
    0x500500788: int[2]= 1 
    0x50050078c: int[3]= 1 
    0x500500790: int[4]= 1 
    0x500500794: int[5]= 1 
    0x500500798: int[6]= 1 
    0x50050079c: int[7]= 1 
    0x5005007a0: int[8]= 1 
    0x5005007a4: int[9]= 1 
    0x5005007a8: int[10]= 1 
    0x5005007ac: int[11]= 1 
    0x5005007b0: int[12]= 0 
    GpuDumpIntMemory<<<1,1>>>(0x500100818, 13, 0) TotThrds=1  ** Dest of 2nd copy 
    0x500100818: int[0]= 0 
    0x50010081c: int[1]= 0 
    0x500100820: int[2]= 0 
    0x500100824: int[3]= 0 
    0x500100828: int[4]= 0 
    0x50010082c: int[5]= 0 
    0x500100830: int[6]= 0 
    0x500100834: int[7]= 0 
    0x500100838: int[8]= 0 
    0x50010083c: int[9]= 0 
    0x500100840: int[10]= 0 
    0x500100844: int[11]= 0 
    0x500100848: int[12]= 0 

Следующие работает правильно:

cudaMemcpyToSymbol(flt,pFlts,1920,0,cudaMemcpyDeviceToDevice); // first copy 
int* pTemp; 
cudaGetSymbolAddress((void**) &pTemp, ints); 
cudaMemcpy(ints,pFlts+480,640,cudaMemcpyDeviceToDevice); // second copy 

Результаты:

GpuDumpFloatMemory<<<1,1>>>(0x500500000, 13, 320) TotThrds=1 ** Source of first copy 
    0x500500500: float[320]= 1.000 
    0x500500504: float[321]= 0.866 
    0x500500508: float[322]= 0.500 
    0x50050050c: float[323]= -0.000 
    0x500500510: float[324]= -0.500 
    0x500500514: float[325]= -0.866 
    0x500500518: float[326]= -1.000 
    0x50050051c: float[327]= -0.866 
    0x500500520: float[328]= -0.500 
    0x500500524: float[329]= 0.000 
    0x500500528: float[330]= 0.500 
    0x50050052c: float[331]= 0.866 
    0x500500530: float[332]= 1.000 
    GpuDumpFloatMemory<<<1,1>>>(0x500100a98, 13, 320) TotThrds=1 ** Dest of first copy 
    0x500100f98: float[320]= 1.000 
    0x500100f9c: float[321]= 0.866 
    0x500100fa0: float[322]= 0.500 
    0x500100fa4: float[323]= -0.000 
    0x500100fa8: float[324]= -0.500 
    0x500100fac: float[325]= -0.866 
    0x500100fb0: float[326]= -1.000 
    0x500100fb4: float[327]= -0.866 
    0x500100fb8: float[328]= -0.500 
    0x500100fbc: float[329]= 0.000 
    0x500100fc0: float[330]= 0.500 
    0x500100fc4: float[331]= 0.866 
    0x500100fc8: float[332]= 1.000 
    GpuDumpIntMemory<<<1,1>>>(0x500500780, 13, 0) TotThrds=1 ** Source of 2nd copy 
    0x500500780: int[0]= 1 
    0x500500784: int[1]= 1 
    0x500500788: int[2]= 1 
    0x50050078c: int[3]= 1 
    0x500500790: int[4]= 1 
    0x500500794: int[5]= 1 
    0x500500798: int[6]= 1 
    0x50050079c: int[7]= 1 
    0x5005007a0: int[8]= 1 
    0x5005007a4: int[9]= 1 
    0x5005007a8: int[10]= 1 
    0x5005007ac: int[11]= 1 
    0x5005007b0: int[12]= 0 
    GpuDumpIntMemory<<<1,1>>>(0x500100818, 13, 0) TotThrds=1 ** Destination of 2nd copy 
    0x500100818: int[0]= 1 
    0x50010081c: int[1]= 1 
    0x500100820: int[2]= 1 
    0x500100824: int[3]= 1 
    0x500100828: int[4]= 1 
    0x50010082c: int[5]= 1 
    0x500100830: int[6]= 1 
    0x500100834: int[7]= 1 
    0x500100838: int[8]= 1 
    0x50010083c: int[9]= 1 
    0x500100840: int[10]= 1 
    0x500100844: int[11]= 1 
    0x500100848: int[12]= 0 

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

+0

Вы делаете проверку ошибок на своих вызовах cuda? Вам был приведен пример [здесь] (http://stackoverflow.com/questions/14968293/copy-symbol-address-to-symbol). –

+0

Да, я не включил макрос, который выполняет проверку. Ошибок не сообщается. (cudaSuccess) – Doug

+2

Смещение применяется к символу, а не к источнику. Это твоя проблема. – talonmies

ответ

3

Вторая копия выглядит сломанной для меня. Вы определили этот массив:

__constant__ int ints[160]; // 640 bytes 

который, как указано правильно, составляет 640 байт.

Ваша вторая копия, как это:

cudaMemcpyToSymbol(ints,pFlts,640,1920,cudaMemcpyDeviceToDevice); // second copy 

Который говорит, «скопировать в общей сложности 640 байт, из pFlts массива ints массива с места хранения в ints массиве, начиная с 1920-х байтов от начало массива. "

Это не сработает. Массив ints имеет длину всего 640 байт. Вы не можете выбрать в качестве места назначения место, в которое в него входит 1920 байт.

Из документации для cudaMemcpyToSymbol:

offset- Смещение от начала символа в байтах

В этом случае символ ints

Возможно, что вы хотите:

cudaMemcpyToSymbol(ints,pFlts+480,640,0,cudaMemcpyDeviceToDevice); // second copy 

EDIT: В ответ на вопросы в комментариях о проверке ошибок, я вписываться этот простую тестовую программу:

#include <stdio.h> 

#define cudaCheckErrors(msg) \ 
    do { \ 
     cudaError_t __err = cudaGetLastError(); \ 
     if (__err != cudaSuccess) { \ 
      fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \ 
       msg, cudaGetErrorString(__err), \ 
       __FILE__, __LINE__); \ 
      fprintf(stderr, "*** FAILED - ABORTING\n"); \ 
      exit(1); \ 
     } \ 
    } while (0) 

__constant__ int ints[160]; 

int main(){ 

    int *d_ints; 
    cudaError_t mystatus; 

    cudaMalloc((void **)&d_ints, sizeof(int)*160); 
    cudaCheckErrors("cudamalloc fail"); 
    mystatus = cudaMemcpyToSymbol(ints, d_ints, 160*sizeof(int), 1920, cudaMemcpyDeviceToDevice); 
    if (mystatus != cudaSuccess) printf("returned value was not cudaSuccess\n"); 
    cudaCheckErrors("cudamemcpytosymbol fail"); 

    printf("OK!\n"); 
    return 0; 
} 

Когда я скомпилировать и запустить это, я получаю следующий результат:

returned value was not cudaSuccess 
Fatal error: cudamemcpytosymbol fail (invalid argument at t94.cu:26) 
*** FAILED - ABORTING 

Это указывает на то, что как ошибка возвращаемое значение вызова функции cudaMemcpyToSymbol и метода cudaGetLastError() возвращает ошибку в этом случае. Если я изменю параметр 1920 на ноль в этом случае, ошибка исчезнет.

+0

Да, я использовал СМЕЩЕНИЕ как смещение в исходное, а не в пункт назначения. (Bassackwards) Спасибо – Doug

Смежные вопросы