2012-12-21 25 views
7

Tôi biết rằng "mỗi sợi dọc chứa các chuỗi liên tiếp, tăng ID luồng với sợi dọc đầu tiên chứa chuỗi 0" vì vậy 32 luồng đầu tiên phải nằm trong sợi dọc đầu tiên. Ngoài ra tôi biết rằng tất cả các chủ đề trong một dọc được thực hiện đồng thời trên bất kỳ bộ xử lý đa luồng nào có sẵn.CUDA. Làm thế nào để unroll 32 chủ đề đầu tiên để họ sẽ được thực hiện song song?

Như tôi đã hiểu, vì điều đó không cần đồng bộ chuỗi nếu chỉ có một warp đang được thực thi. Nhưng mã bên dưới tạo ra câu trả lời sai nếu tôi xóa bất kỳ số nào trong số __syncthreads() trong áp chót if khối. Tôi đã cố gắng tìm ra nguyên nhân nhưng cuối cùng lại chẳng có gì. Tôi thực sự hy vọng sự giúp đỡ của bạn, vì vậy bạn có thể cho tôi biết những gì là sai với mã này? Tại sao tôi không thể để lại chỉ __syncthreads() cuối cùng và nhận được câu trả lời đúng?

#define BLOCK_SIZE 128 

__global__ void reduce (int * inData, int * outData) 
{ 
__shared__ int data [BLOCK_SIZE]; 
int tid = threadIdx.x; 
int i = blockIdx.x * blockDim.x + threadIdx.x; 

data [tid] = inData [i] + inData [i + blockDim.x/2 ]; 
__syncthreads(); 

for (int s = blockDim.x/4; s > 32; s >>= 1) 
{ 
    if (tid < s) 
    data [tid] += data [tid + s]; 
    __syncthreads(); 
} 

if (tid < 32) 
{ 
    data [tid] += data [tid + 32]; 
    __syncthreads(); 
    data [tid] += data [tid + 16]; 
    __syncthreads(); 
    data [tid] += data [tid + 8]; 
    __syncthreads(); 
    data [tid] += data [tid + 4]; 
    __syncthreads(); 
    data [tid] += data [tid + 2]; 
    __syncthreads(); 
    data [tid] += data [tid + 1]; 
    __syncthreads(); 
} 
if (tid == 0) 
    outData [blockIdx.x] = data [0]; 
} 

void main() 
{ 
... 
reduce<<<dim3(128), dim3(128)>>>(dev_data, dev_res); 
... 
} 

P.S. Tôi đang sử dụng GT560Ti

Trả lời

7

Bạn nên khai báo biến bộ nhớ chia sẻ là dễ bay hơi:

__shared__ volatile int data [BLOCK_SIZE]; 

Vấn đề bạn đang nhìn thấy là một artifact của kiến ​​trúc Fermi và trình biên dịch tối ưu hóa. Kiến trúc Fermi thiếu hướng dẫn để hoạt động trực tiếp trên bộ nhớ dùng chung (chúng có mặt trong dòng G80/90/GT200). Vì vậy, tất cả mọi thứ được nạp để đăng ký, thao tác, và được lưu trữ trở lại bộ nhớ chia sẻ. Nhưng trình biên dịch là miễn phí để suy ra rằng mã có thể được thực hiện nhanh hơn nếu một loạt các hoạt động đã được tổ chức trong đăng ký, không có tải trung gian và các cửa hàng từ/đến bộ nhớ chia sẻ. Điều này là hoàn toàn tốt đẹp ngoại trừ khi bạn đang dựa vào đồng bộ hóa ngầm của các chủ đề trong cùng một chiến dịch thao tác bộ nhớ dùng chung, như trong loại mã giảm này.

Bằng cách tuyên bố bộ nhớ chia sẻ là dễ bay hơi, bạn buộc trình biên dịch thực thi ghi bộ nhớ chia sẻ sau mỗi giai đoạn giảm và đồng bộ hóa dữ liệu ngầm giữa các chủ đề trong dọc được khôi phục.

Vấn đề này được thảo luận trong các ghi chú lập trình cho Fermi có thể vận chuyển (hoặc có thể được vận chuyển) bằng bộ công cụ CUDA.

Các vấn đề liên quan