2009-05-08 16 views
14

Tôi đã vật lộn với điều này cả ngày, tôi đang cố gắng để có được một máy phát điện số ngẫu nhiên cho các chủ đề trong mã CUDA của tôi. Tôi đã xem qua tất cả các diễn đàn và có chủ đề này đi lên một chút công bằng nhưng tôi đã dành nhiều giờ cố gắng để làm sáng tỏ tất cả các loại mã để avail không có. Nếu bất cứ ai biết về một phương pháp đơn giản, có thể là một hạt nhân có thể được gọi để trả về một dấu phẩy ngẫu nhiên giữa 0 và 1, hoặc một số nguyên mà tôi có thể biến đổi, tôi sẽ biết ơn nhất.Máy phát điện số ngẫu nhiên trong CUDA

Một lần nữa, tôi hy vọng sẽ sử dụng số ngẫu nhiên trong hạt nhân, giống như rand() chẳng hạn.

Cảm ơn trước

+0

Một số thông tin hữu ích: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch37.html – Jesper

Trả lời

5

Tôi không chắc tôi hiểu tại sao bạn cần bất kỳ điều gì đặc biệt. Bất kỳ PRNG truyền thống nào cũng nên trực tiếp khai thác nhiều hơn hoặc ít hơn. A linear congruential sẽ hoạt động tốt. Bạn có một số đặc tính đặc biệt mà bạn đang cố gắng thiết lập không?

+0

Tôi nghĩ rằng anh ấy đang tìm kiếm một thư viện mà anh ấy có thể gọi, chứ không phải để tự mình thực hiện. Vẫn là một câu trả lời tốt để chỉ cho anh ta một giải pháp. – lothar

+0

Tính đồng tuyến tuyến tính rất đơn giản để thực hiện. Bạn có thể làm điều này với CUDA bằng cách có một PRNG riêng biệt với trạng thái riêng của nó trong mỗi luồng. –

+0

Đó là điều khiến tôi hơi bối rối. Mỗi chủ đề sẽ được hạt giống từ id chủ đề của nó, nhưng họ sẽ không đủ sớm bắt đầu chồng chéo? – zenna

2

Có gói MDGPU (GPL) bao gồm việc triển khai hàm rand48() của GNU cho CUDA here.

Tôi đã tìm thấy nó (khá dễ dàng, sử dụng Google, mà tôi cho rằng bạn đã thử :-) trên diễn đàn NVidia here.

+0

Vâng tôi cũng đã tìm thấy điều đó .. nhưng cố gắng làm cho nó làm những gì tôi muốn .. Tôi nghĩ rằng tôi chỉ có một ngày ngu ngốc .. Tôi sẽ kiểm tra lại, cảm ơn – zenna

+0

Theo nhận xét trong NVidia diễn đàn (bao gồm cả tác giả) việc triển khai không hoạt động tốt. –

2

tôi đã không tìm thấy một bộ tạo số song song tốt cho CUDA, tuy nhiên tôi đã tìm thấy một bộ tạo số ngẫu nhiên song song dựa trên nghiên cứu học tập ở đây: http://sprng.cs.fsu.edu/

+0

Có ai biết phiên bản CUDA của thuật toán này không? –

+0

Bạn có ý nghĩa gì bởi "tốt"? Tùy thuộc vào yêu cầu của bạn, một băm MD5 đơn giản (xem cuDPP) có thể là đủ. Đối với một số trường hợp, nhiều Mersenne Twisters có thể là tốt nhất vì chúng có thời gian thực sự lâu dài và độc lập tốt giữa các luồng. NAG có MRG32k3a của l'Ecatcher hoạt động thực sự tốt nếu bạn cần một luồng đơn trên nhiều luồng/khối. – Tom

+0

Một khởi đầu tốt sẽ là một bộ tạo số ngẫu nhiên lặp đi lặp lại với sự phụ thuộc thấp giữa các ô - thích hợp, để tạo một tập hợp các mảng số ngẫu nhiên, điền nội dung của mỗi mảng với nhiều luồng, nhưng tạo ra một mảng. –

4

Tùy thuộc vào ứng dụng của bạn, bạn nên thận trọng khi sử dụng LCGs mà không xem xét liệu các luồng (một luồng trên mỗi luồng) sẽ trùng lặp hay không. Bạn có thể thực hiện một bước nhảy vọt với LCG, nhưng sau đó bạn sẽ cần phải có một LCG thời gian đủ dài để đảm bảo rằng trình tự không lặp lại.

Một ví dụ leapfrog có thể là:

template <typename ValueType> 
__device__ void leapfrog(unsigned long &a, unsigned long &c, int leap) 
{ 
    unsigned long an = a; 
    for (int i = 1 ; i < leap ; i++) 
     an *= a; 
    c = c * ((an - 1)/(a - 1)); 
    a = an; 
} 

template <typename ValueType> 
__device__ ValueType quickrand(unsigned long &seed, const unsigned long a, const unsigned long c) 
{ 
    seed = seed * a; 
    return seed; 
} 

template <typename ValueType> 
__global__ void mykernel(
    unsigned long *d_seeds) 
{ 
    // RNG parameters 
    unsigned long a = 1664525L; 
    unsigned long c = 1013904223L; 
    unsigned long ainit = a; 
    unsigned long cinit = c; 
    unsigned long seed; 

    // Generate local seed 
    seed = d_seeds[bid]; 
    leapfrog<ValueType>(ainit, cinit, tid); 
    quickrand<ValueType>(seed, ainit, cinit); 
    leapfrog<ValueType>(a, c, blockDim.x); 

    ... 
} 

Nhưng rồi thời gian của máy phát điện đó có lẽ là không đủ trong hầu hết các trường hợp.

Thành thật mà nói, tôi sẽ xem xét sử dụng thư viện của bên thứ ba chẳng hạn như NAG. Có một số máy tạo hàng loạt trong SDK cũng vậy, nhưng đó có thể không phải là những gì bạn đang tìm kiếm trong trường hợp này.

EDIT

Vì đây chỉ đã lên-bình chọn, tôi hình dung nó có giá trị cập nhật kể rằng cuRAND, như đã đề cập bởi câu trả lời gần đây hơn cho câu hỏi này, có sẵn và cung cấp một số máy phát điện và phân phối. Đó chắc chắn là nơi dễ nhất để bắt đầu.

9

Đối với bất kỳ ai quan tâm, bạn hiện có thể thực hiện điều đó qua cuRAND.

4

Cách tốt nhất cho điều này được viết riêng thiết bị chức năng của bạn, đây là một trong những

void RNG() 
{ 
    unsigned int m_w = 150; 
    unsigned int m_z = 40; 

    for(int i=0; i < 100; i++) 
    { 
     m_z = 36969 * (m_z & 65535) + (m_z >> 16); 
     m_w = 18000 * (m_w & 65535) + (m_w >> 16); 

     cout <<(m_z << 16) + m_w << endl; /* 32-bit result */ 
    } 
} 

Nó sẽ cung cấp cho bạn 100 số ngẫu nhiên với kết quả 32 bit.

Nếu bạn muốn một số con số ngẫu nhiên giữa 1 và 1000, bạn cũng có thể lấy result%1000, hoặc tại các điểm tiêu thụ, hoặc tại thời điểm thế hệ:

((m_z << 16) + m_w)%1000 

Thay đổi m_w và m_z bắt đầu giá trị (trong ví dụ 150 và 40) cho phép bạn nhận được kết quả khác nhau mỗi lần. Bạn có thể sử dụng threadIdx.x làm một trong số đó, mỗi lần sẽ cung cấp cho bạn loạt giả ngẫu nhiên khác nhau.

tôi muốn thêm rằng nó hoạt động 2 lần nhanh hơn so với rand() chức năng, và các công trình lớn;)

+3

Nhận xét của biên tập viên: Đó là một RNG nhỏ gọn, nhưng không có nơi nào có thể sử dụng được để tính toán khi có số ngẫu nhiên tốt. Nó có một khoảng thời gian 2^16, nó không thể kéo dài toàn bộ không gian số 32 bit, và nó là khá dễ dàng đảo ngược do một bước đơn giản và thời gian nhỏ. – qdot

4

Tôi nghĩ rằng bất kỳ cuộc thảo luận về vấn đề này cần phải trả lời yêu cầu ban đầu Zenna và đó là cho một mức độ chủ đề triển khai. Cụ thể là một chức năng của thiết bị có thể được gọi từ bên trong một hạt nhân hoặc sợi hoặc sợi. Xin lỗi nếu tôi quá nhiều cụm từ "in đậm" nhưng tôi thực sự nghĩ rằng câu trả lời cho đến nay không hoàn toàn giải quyết những gì đang được tìm kiếm ở đây.

Thư viện cuRAND là đặt cược tốt nhất của bạn. Tôi đánh giá cao rằng mọi người đang muốn phát minh lại bánh xe (nó làm cho một trong những đánh giá cao và sử dụng đúng hơn các thư viện của bên thứ 3) nhưng máy phát điện số chất lượng cao hiệu suất cao rất phong phú và được thử nghiệm tốt. Thông tin tốt nhất tôi có thể đề xuất là trên tài liệu cho thư viện GSL trên các máy phát điện khác nhau tại đây: http://www.gnu.org/software/gsl/manual/html_node/Random-number-generator-algorithms.html

Đối với bất kỳ mã nào nghiêm trọng, tốt nhất nên sử dụng một trong các thuật toán chính mà nhà toán học/máy tính và tìm kiếm những điểm yếu hệ thống. Các "mersenne twister" là một cái gì đó với một khoảng thời gian (lặp lại vòng lặp) vào thứ tự 10^6000 (thuật toán MT19997 có nghĩa là "Mersenne Twister 2^19997") đã được đặc biệt thích nghi cho Nvidia để sử dụng ở cấp độ thread trong các chủ đề của cùng một sợi dọc bằng cách sử dụng các cuộc gọi id luồng như hạt giống. Xem giấy tại đây: http://developer.download.nvidia.com/compute/cuda/2_2/sdk/website/projects/MersenneTwister/doc/MersenneTwister.pdf. Tôi đang thực sự làm việc để thực hiện somehting bằng cách sử dụng thư viện này và NẾU tôi nhận được nó để làm việc đúng cách tôi sẽ đăng mã của tôi. Nvidia có một số ví dụ tại trang tài liệu của họ cho bộ công cụ CUDA hiện tại.

LƯU Ý: Chỉ cần cho bản ghi tôi không làm việc cho Nvidia, nhưng tôi sẽ thừa nhận tài liệu và thiết kế trừu tượng của họ cho CUDA là điều mà tôi có ấn tượng với nó.


0

Bạn có thể thử ra Mersenne Twister for GPUs

Nó dựa trên SIMD hướng nhanh Mersenne Twister (SFMT) mà là một bộ tạo số ngẫu nhiên khá nhanh và đáng tin cậy. Nó vượt qua các thử nghiệm của Marsaglias DIEHARD cho các bộ tạo số ngẫu nhiên.

+0

cuRAND đã [cung cấp mersenne twister] (http://docs.nvidia.com/cuda/curand/acknowledgements.html#acknowledgements) được triển khai cho GPU. –