2012-06-26 2 views
8

Я хотел бы назвать что-то вроде usleep() внутри ядра CUDA. Основная цель заключается в том, чтобы все ядра GPU спали или заняты в течение нескольких миллисекунд - это часть некоторых проверок здравомыслия, которые я хочу сделать для приложения CUDA. Моя попытка сделать это ниже:Эквивалент usleep() в ядре CUDA?

#include <unistd.h> 
#include <stdio.h> 
#include <cuda.h> 
#include <sys/time.h> 

__global__ void gpu_uSleep(useconds_t wait_time_in_ms) 
{ 
    usleep(wait_time_in_ms); 
} 

int main(void) 
{ 
    //input parameters -- arbitrary 
    // TODO: set these exactly for full occupancy 
    int m = 16; 
    int n = 16; 
    int block1D = 16; 
    dim3 block(block1D, block1D); 
    dim3 grid(m/block1D, n/block1D); 

    useconds_t wait_time_in_ms = 1000; 

    //execute the kernel 
    gpu_uSleep<<< grid, block >>>(wait_time_in_ms); 
    cudaDeviceSynchronize(); 

    return 0; 
} 

Я получаю следующее сообщение об ошибке, когда я пытаюсь скомпилировать это с помощью NVCC:

error: calling a host function("usleep") from a __device__/__global__ 
     function("gpu_uSleep") is not allowed 

Очевидно, что я не разрешено использовать функцию хозяина, такие как usleep() внутри ядра. Что было бы хорошей альтернативой этому?

ответ

9

Вы можете занят ждать с помощью цикла, который читает clock().

Ждать, по крайней мере, 10000 тактовых циклов:

clock_t start = clock(); 
clock_t now; 
for (;;) { 
    now = clock(); 
    clock_t cycles = now > start ? now - start : now + (0xffffffff - start); 
    if (cycles >= 10000) { 
    break; 
    } 
} 
// Stored "now" in global memory here to prevent the 
// compiler from optimizing away the entire loop. 
*global_now = now; 

Примечание: Это не тестировалась. Код, который обрабатывает переполнения, был заимствован от this answer by @Pedro. См. Его ответ и раздел B.10 в Руководстве по программированию CUDA C 4.2 для получения подробной информации о том, как работает clock(). Существует также команда clock64().

+0

Спасибо! Я хотел бы использовать clock64() так, чтобы я мог рассчитывать дольше и уменьшать влияние перекатывания. Когда я компилирую ядро ​​CUDA, которое включает вызов clock64(), я получаю «error: identifier» clock64 «undefined». Когда я использую clock(), программа компилируется правильно. Я использую nvcc 4.0. Основываясь на быстром поиске google, кажется, что clock64() должен находиться в cuda/nvcc 4.0. Любые мысли о том, как это решить? – solvingPuzzles

+2

Вам также нужна вычислительная способность> = 2.0, чтобы получить 'clock64()'. –

+0

интересный. Я использую GTX480, который перечисляет nvidia как имеющий возможность вычисления 2.0. – solvingPuzzles

17

Вы можете вращаться на часах() или clock64(). Эталон CUDA SDK concurrentKernels делает следующее:

__global__ void clock_block(clock_t *d_o, clock_t clock_count) 
{ 
    clock_t start_clock = clock(); 
    clock_t clock_offset = 0; 
    while (clock_offset < clock_count) 
    { 
     clock_offset = clock() - start_clock; 
    } 
    d_o[0] = clock_offset; 
} 

Я рекомендую использовать clock64(). clock() и clock64() находятся в циклах, поэтому вам придется запрашивать частоту с помощью cudaDeviceProperties(). Частота может быть динамической, поэтому трудно гарантировать точную спиновую петлю.

+3

+1 для примечания о частотах –

+1

Никогда не поздно, чтобы поддержать надежный ответ, тем более, что имя ядра настолько забавно. Это было намеренно? – JorenHeit

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