2012-06-26 17 views
8

Tôi muốn gọi một cái gì đó như usleep() bên trong một hạt nhân CUDA. Mục tiêu cơ bản là làm cho tất cả các lõi GPU ngủ hoặc bận rộn với một số millescond - đó là một phần của một số kiểm tra độ chính xác mà tôi muốn làm cho một ứng dụng CUDA. nỗ lực của tôi lúc làm điều này là dưới đây:Tương đương với việc ngủ() trong hạt nhân 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; 
} 

tôi nhận được lỗi sau khi tôi cố gắng biên dịch này sử dụng NVCC:

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

Rõ ràng, tôi không được phép sử dụng một chức năng máy chủ như usleep() bên trong hạt nhân. Điều gì sẽ là một lựa chọn tốt cho điều này?

Trả lời

9

Bạn có thể đợi với vòng lặp đọc số clock().

Để chờ ít nhất 10.000 chu kỳ đồng hồ:

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; 

Lưu ý: Đây là chưa được kiểm tra. Mã xử lý tràn được mượn từ this answer bởi @Pedro. Xem câu trả lời và phần B.10 của mình trong Hướng dẫn lập trình CUDA 4.2 để biết chi tiết về cách hoạt động của clock(). Ngoài ra còn có một lệnh clock64().

+0

Cảm ơn! Tôi muốn sử dụng clock64() để tôi có thể đếm lâu hơn và giảm tác động của việc lăn lộn. Khi tôi biên dịch một hạt nhân CUDA bao gồm một cuộc gọi clock64(), tôi nhận được "lỗi: định danh" clock64 "là không xác định." Khi tôi sử dụng clock(), chương trình sẽ biên dịch đúng cách. Tôi đang sử dụng nvcc 4.0. Dựa trên tìm kiếm google nhanh, có vẻ như clock64() được cho là nằm trong cuda/nvcc 4.0. Bất kỳ suy nghĩ về cách giải quyết này? – solvingPuzzles

+2

Bạn cũng cần khả năng tính toán> = 2.0 để có được 'clock64()'. –

+0

thú vị. Tôi đang sử dụng một GTX480, mà nvidia liệt kê là có khả năng tính toán 2.0. – solvingPuzzles

17

Bạn có thể quay trên đồng hồ() hoặc clock64(). Mẫu CUDA SDK concurrentKernels thực hiện như sau:

__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; 
} 

Tôi khuyên bạn nên sử dụng clock64(). clock() và clock64() đang trong chu kỳ, do đó bạn sẽ phải truy vấn tần số bằng cudaDeviceProperties(). Tần số có thể động vì vậy sẽ rất khó để đảm bảo vòng quay chính xác.

+3

+1 để nhận xét về tần số –

+1

Không bao giờ quá muộn để upvote một câu trả lời rắn, đặc biệt là kể từ khi tên hạt nhân là rất buồn cười. Điều đó có chủ ý không? – JorenHeit