2014-09-05 38 views
0

在C++中使用VexCL我試圖計算向量中的所有值超過一定的最小值,並且我想在設備上執行此計數。默認的Reducers只提供了MIN,MAX和SUM的方法,並且這些例子並沒有清楚地說明如何執行這樣的操作。此代碼是緩慢的,因爲它可能是主機的設備,而不是在執行:VexCL:向量中的值的數量高於最小值

int amount = 0; 
int minimum = 5; 

for (vex::vector<int>::iterator i = vector.begin(); i != vector.end(); ++i) 
{ 
    if (*i >= minimum) 
    { 
     amount++; 
    } 
} 

我使用將向量由大量值的,說百萬,大多是零。除了最小值以上的值之外,我還想檢索包含這些值的向量ID列表。這可能嗎?

+0

我不知道關於VexCL,但在主機端,你應該使用['count_if'](http://en.cppreference.com/w/cpp/algorithm/count)而不是自己循環。 VexCL沒有類似的東西? – 2014-09-05 11:06:03

回答

1

如果你只需要數高於最低元素,這將是一樣簡單

vex::Reductor<int, vex::SUM> sum(ctx); 
int amount = sum(vec >= minimum); 

1和0的序列vec >= minimum表達的結果,sum然後計算的。現在

,因爲你還需要得到最低限度以上元素的位置,它變得有點複雜:

#include <iostream> 
#include <vexcl/vexcl.hpp> 

int main() { 
    vex::Context ctx(vex::Filter::Env && vex::Filter::Count(1)); 

    // Input vector 
    vex::vector<int> vec(ctx, {1, 3, 5, 2, 6, 8, 0, 2, 4, 7}); 
    int n = vec.size(); 
    int minimum = 5; 

    // Put result of (vec >= minimum) into key, and element indices into pos: 
    vex::vector<int> key(ctx, n); 
    vex::vector<int> pos(ctx, n); 

    key = (vec >= minimum); 
    pos = vex::element_index(); 

    // Get number of interesting elements in vec. 
    vex::Reductor<int, vex::SUM> sum(ctx); 
    int amount = sum(key); 

    // Sort pos by key in descending order. 
    vex::sort_by_key(key, pos, vex::greater<int>()); 

    // First 'amount' of elements in pos now hold indices of interesting 
    // elements. Lets use slicer to extract them: 
    vex::vector<int> indices(ctx, amount); 

    vex::slicer<1> slice(vex::extents[n]); 
    indices = slice[vex::range(0, amount)](pos); 

    std::cout << "indices: " << indices << std::endl; 
} 

這給出了以下的輸出:

indices: { 
    0:  2  4  5  9 
} 
0

@ddemidov

感謝您的幫助,它工作。但是,它比我的原始代碼慢得多,它將設備向量複製到主機並使用Boost進行排序。下面是示例代碼與一些定時:

#include <iostream> 
#include <cstdio> 
#include <vexcl/vexcl.hpp> 
#include <vector> 
#include <boost/range/algorithm.hpp> 

int main() 
{ 
    clock_t start, end; 

    // initialize vector with random numbers 
    std::vector<int> hostVector(1000000); 
    for (int i = 0; i < hostVector.size(); ++i) 
    { 
     hostVector[i] = rand() % 20 + 1; 
    } 

    // copy to device 
    vex::Context cpu(vex::Filter::Type(CL_DEVICE_TYPE_CPU) && vex::Filter::Any); 
    vex::Context gpu(vex::Filter::Type(CL_DEVICE_TYPE_GPU) && vex::Filter::Any); 
    vex::vector<int> vectorCPU(cpu, 1000000); 
    vex::vector<int> vectorGPU(gpu, 1000000); 
    copy(hostVector, vectorCPU); 
    copy(hostVector, vectorGPU); 

    // sort results on CPU 
    start = clock(); 
    boost::sort(hostVector); 
    end = clock(); 
    cout << "C++: " << (end - start)/(CLOCKS_PER_SEC/1000) << " ms" << endl; 

    // sort results on OpenCL 
    start = clock(); 
    vex::sort(vectorCPU, vex::greater<int>()); 
    end = clock(); 
    cout << "vexcl CPU: " << (end - start)/(CLOCKS_PER_SEC/1000) << " ms" << endl; 

    start = clock(); 
    vex::sort(vectorGPU, vex::greater<int>()); 
    end = clock(); 
    cout << "vexcl GPU: " << (end - start)/(CLOCKS_PER_SEC/1000) << " ms" << endl; 

    return 0; 
} 

這導致:使用I7 3770 CPU和(慢)HD4650顯卡

C++: 17 ms 
vexcl CPU: 737 ms 
vexcl GPU: 1670 ms 

。正如我讀過OpenCL應該能夠在大型頂點上執行快速排序。你有什麼建議如何使用OpenCL和vexcl進行快速排序?

+0

您不應該對第一次調用'vex :: sort()'(在兩個設備上)進行測量,因爲它包含OpenCL編譯開銷。這裏是鏈接到您的修改源:https://gist.github.com/ddemidov/cf141c97aa22de32c22d,這將導致以下輸出: CPU:Intel(R)Core(TM)i7 CPU 920 @ 2.67GHz(Intel (R)OpenCL) GPU:Tesla K40c(NVIDIA CUDA) C++:34 ms vexcl CPU:281 ms vexcl GPU:1 ms – ddemidov 2014-09-08 12:23:41