2015-11-23 3 views
-1

Я пытаюсь реализовать свой алгоритм на GPU с использованием CUDA. эта программа работает хорошо, но есть проблема. когда я пытаюсь распечатать результаты, они будут показаны слишком поздно. вот некоторые из моих кодов. Предположим, что истинные результаты не имеют значения.Разница между временем выполнения и временем получения результатов в CUDA

__device__ unsigned char dev_state[128]; 

__device__ unsigned char GMul(unsigned char a, unsigned char b) { // Galois Field (256) Multiplication of two Bytes 
    unsigned char p = 0; 
    int counter; 
    unsigned char hi_bit_set; 
    for (counter = 0; counter < 8; counter++) { 
     if ((b & 1) != 0) { 
      p ^= a; 
     } 
     hi_bit_set = a & 0x80; 
     a <<= 1; 
     if (hi_bit_set != 0) { 
      a ^= 0x1b; /* x^8 + x^4 + x^3 + x + 1 */ 
     } 
     b >>= 1; 
    } 
    return p; 
} 


__global__ void AESROUND() 
{ 
    __shared__ unsigned char dev_rkey; 
    __shared__ unsigned char dev_sh_state; 
    int state_idx = blockIdx.x; 
    int offset = ((state_idx/4)) *4; 

    for (int i = 0; i < 512; i++) 
    { 
     dev_rkey = dev_state[state_idx]; 

     dev_sh_state= GMul(dev_state[state_idx], 0x02)^GMul(dev_state[(state_idx + 5) % 16], 0x03)^dev_state[(offset + 5) % 16]^dev_state[(offset + 5) % 16]; 


     dev_state[state_idx] = dev_sh_state^dev_rkey; 
    } 


} 

вызова AESROUND

int main() 
{ 

    unsigned char p[] = { 0x19, 0x3d, 0xe3, 0xbe, 0xa0, 0xf4, 0xe2, 0x2b, 0x9a, 0xc6, 0x8d, 0x2a, 0xe9, 0xf8, 0x48, 0x08 }; 

unsigned char h_state[128]; 
for (long long i = 0; i < 128; i++) 
    h_state[i] = p[i%16]; 

cudaMemcpyToSymbolAsync(dev_state, h_state, 128, 0, cudaMemcpyHostToDevice); 

clock_t start, finish; 

start = clock(); 
for (long long i = 0; i < 1024; i++) 

    AESROUND << <128, 128 >> >(); 
finish = clock(); 

float Time = finish - start; 

printf("\n\nprocessing time: %2.15f (ms)\n", Time); 

cudaMemcpyFromSymbolAsync(h_state, dev_state, 128, 0, cudaMemcpyDeviceToHost); 
printf("\n\state After Encryption:\n "); 
for (int i = 0; i < 16; i++) 
    printf("%x ", h_state[i]); 

getchar(); 
return 0; 
} 

вот результаты:

processing time: 1.0000000000000 (ms) 

-После длительное время (~ 5 секунд), следующая строка будет shown-

state after encryption: 
88 91 23 09 78 65 11 87 65 43 56 71 20 93 18 70 

, как вы можете видеть, время обработки слишком быстрое, но 128Byte будет отображаться слишком поздно. почему это произошло? это связано с GPU? как я могу это исправить?

+2

Там нет ничего, чтобы исправить. Ваш тайм-аут ядра неправильный, и вы измеряете время запуска ядра, а не время выполнения. – talonmies

+3

Чтобы расширить то, что сказал @talonmies: ядра по умолчанию запускаются асинхронно. Вы можете принудительно выполнить синхронизацию, вызвав 'cudaDeviceSynchronize()' после запуска ядра (до 'finish = clock()'), чтобы получить «истинное» время выполнения. Кроме того, вы можете немного прочитать о поведении асинхронной памяти: http://developer.download.nvidia.com/compute/cuda/4_1/rel/toolkit/docs/online/sync_async.html (я не сделал найти онлайн-версию этого для новых версий CUDA, но там содержится основная информация) – Marco13

+1

@ Marco13: обновленную онлайн-версию API-интерфейса CUDA можно найти здесь [https: //docs.nvidia .com/cuda/cuda-runtime-api/index.html) – njuffa

ответ

2

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

Запуск ядра асинхронный. Код хоста запускает ядро, а затем продолжается, не дожидаясь завершения ядра. Поэтому такой тип времени:

start = clock(); 
for (long long i = 0; i < 1024; i++) 

    AESROUND << <128, 128 >> >(); 
finish = clock(); 

измеряет только время запуска ядра. (Это верно даже в том случае, когда ядро ​​запускается несколько раз в цикле.Если некоторые очереди устройств не превышены, каждый запуск ядра будет асинхронным, позволяя продолжить хост-поток, т. Е. Для цикла.)

для того, чтобы измерить полное время выполнения устройства, вы могли бы сделать что-то вроде этого:

start = clock(); 
for (long long i = 0; i < 1024; i++) 

    AESROUND << <128, 128 >> >(); 
cudaDeviceSynchronize(); //wait for device to finish 
finish = clock();