2014-01-18 181 views
0

我試圖並行實現多個top-k選擇,其中每個選擇從n個元素列表中選擇k個元素,並且有m個這樣的任務要並行執行。我使用幼崽來做到這一點。我有一個奇怪的錯誤,我不知道我做錯了什麼。我覺得我的理解可能會犯一些明顯的錯誤,有人可以幫我檢查一下嗎?cuda和cub實現多個k選擇

編輯:

我把它通過增加兩個cudaDeviceSynchronize()電話,每個包含free()兩個代碼段的前工作。所以,現在我的問題是,是否free行爲不同於cudaFree,在異步調用立即着手這是不允許的,而不是到另一個問題,我在這裏問:Does cudaFree after asynchronous call work?

// Assume dtop has size k x m and dmat has size n x m, where k < n 
// Each column of dtop is supposed to obtain the top-k indices of 
// elements from the corresponding column in dmat. 
template<typename ValueType, typename IndexType> 
void TopKPerColumn_cub_test(DenseMatrix<IndexType, MemDev> dtop, 
    DenseMatrix<ValueType, MemDev, Const> dmat); 

template<typename T> 
struct SelectLE { 
    T x_; 
    __device__ SelectLE(const T& x):x_(x){} 
    __device__ bool operator() (const T& a) { 
    return a > x_; 
    } 
}; 

template<typename ValueType, typename IndexType> 
__global__ void k_TopKPerColumn_cub_test(DenseMatrix<IndexType, MemDev> dtop, 
    DenseMatrix<ValueType, MemDev, Const> dmat) { 
    int n = dmat.num_rows(); 
    int k = dtop.num_rows(); 

    cub::DoubleBuffer<ValueType> keys; 
    keys.d_buffers[0] = reinterpret_cast<ValueType*>(
     malloc(sizeof(ValueType) * n)); 
    keys.d_buffers[1] = reinterpret_cast<ValueType*>(
     malloc(sizeof(ValueType) * n)); 
    memcpy(keys.d_buffers[keys.selector], dmat.get_col(blockIdx.x).data(), 
     sizeof(ValueType) * n); 

    void* temp_storage = 0; 
    size_t temp_storage_size = 0; 
    cub::DeviceRadixSort::SortKeysDescending(
     temp_storage, temp_storage_size, keys, n); 
    temp_storage = malloc(temp_storage_size); 
    cub::DeviceRadixSort::SortKeysDescending(
     temp_storage, temp_storage_size, keys, n); 
    ValueType kth = keys.Current()[k-1]; 

    free(temp_storage); 
    free(keys.d_buffers[0]); 
    free(keys.d_buffers[1]); 

    temp_storage = 0; 
    temp_storage_size = 0; 
    int* nb_selected = reinterpret_cast<int*>(malloc(sizeof(int))); 
    SelectLE<ValueType> selector(kth); 

    cub::DeviceSelect::If(temp_storage, temp_storage_size, 
     const_cast<ValueType*>(dmat.get_col(blockIdx.x).data()), 
     dtop.get_col(blockIdx.x).data(), 
     nb_selected, n, selector); 
    temp_storage = malloc(temp_storage_size); 
    cub::DeviceSelect::If(temp_storage, temp_storage_size, 
     const_cast<ValueType*>(dmat.get_col(blockIdx.x).data()), 
     dtop.get_col(blockIdx.x).data(), 
     nb_selected, n, selector); 

    free(nb_selected); 
    free(temp_storage); 
} 

template<typename ValueType, typename IndexType> 
void TopKPerColumn_cub_test(DenseMatrix<IndexType, MemDev> dtop, 
    DenseMatrix<ValueType, MemDev, Const> dmat) { 
    k_TopKPerColumn_cub_test<<<dtop.num_cols(), 1>>>(dtop, dmat); 
} 

回答

1

雖然我能夠使它發揮作用,這個實現比單線程的CPU代碼慢。我最終通過堆排序實現了這一點,並將堆放在共享內存中。表現很好。