需要帮助使用嵌套迭代器 transform_reduce 操作优化推力 cuda 代码

Need help optimizing thrust cuda code with nested iterator transform_reduce operations

我正在编写希望在 GPU 上高效执行的代码。大多数代码很容易矢量化并为并行执行做好准备。 Stack Overflow 上有几个不错的示例,它们对我使用标准嵌套迭代器有所帮助。我有一个部分无法成功地浓缩成一个有效的推力结构。我已经采用了我的代码的那一部分并制作了一个最小的可重现示例。任何有关如何构建此代码的建议或提示都将不胜感激。

谢谢

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
#include <ctime>

#include <thrust/reduce.h>
#include <thrust/device_vector.h>

typedef  thrust::device_vector<double> tDoubleVecDevice;
typedef  tDoubleVecDevice::iterator tDoubleVecDeviceIter;

struct functorB{

    template <typename T>
__host__ __device__
    double operator()(const T &my_tuple){  // do some math
           return ( fmod((thrust::get<0>(my_tuple) * thrust::get<1>(my_tuple)),1.0) );
    }
};
struct functorC {

    template <typename T>
__host__ __device__
    double operator()(const T &my_tuple){   // do some math
           double distance = fabs( fmod((thrust::get<0>(my_tuple) - thrust::get<1>(my_tuple)),1.0));
           return((fmin( distance, 1.0 - distance)) / (5.0));
    }
};

int main(void)
{

    tDoubleVecDevice resF(36);
    tDoubleVecDevice freqI(36);


    tDoubleVecDevice trialTs(128);

    std::srand(std::time(nullptr));
    for(tDoubleVecDeviceIter tIter = trialTs.begin();tIter < trialTs.end(); tIter++ ){
        (*tIter) = rand() % 10 + 1.5;  // make some random numbers
    }
    for(tDoubleVecDeviceIter rIter = resF.begin(), fIter = freqI.begin();fIter < resF.end(); rIter++ ,fIter++){
        (*fIter) = rand() % 10 + 1.5;  // make some random numbers
        (*rIter) = rand() % 10 + 1.5;  // make some random numbers
    }

    tDoubleVecDevice trialRs(36);
    tDoubleVecDevice errorVect(128);


     for( tDoubleVecDeviceIter itTrial = trialTs.begin(), itError = errorVect.begin(); itTrial != trialTs.end(); itTrial++,itError++){


            thrust::transform( (thrust::make_zip_iterator(thrust::make_tuple(thrust::make_constant_iterator<double>(*itTrial), freqI.begin()))),
                               (thrust::make_zip_iterator(thrust::make_tuple(thrust::make_constant_iterator<double>(*itTrial)+36, freqI.end()))),
                               trialRs.begin() ,functorB());

            (*itError) =thrust::transform_reduce(
                                             thrust::make_zip_iterator(thrust::make_tuple(trialRs.begin(),resF.begin())),
                                             thrust::make_zip_iterator(thrust::make_tuple(trialRs.end(),resF.end())),
                                             functorC(),(double) 0,thrust::plus<double>()
                                            );
     }
// finds the index of the minimum element;
    int  minElementIndex = thrust::min_element(errorVect.begin(),errorVect.end()) - errorVect.begin();
    double  result = trialTs[minElementIndex];

    std::cout << "result = " << result;

    return 0;
}

看来您需要将 trialsTs、trialsRs、errorVect、freqI 和 resF 向量扩展到 4608 个元素。这将允许您矢量化循环。从 thrust::iterator_adaptor 派生出 class 来制作一个循环迭代器来扩展您的 freqI 和 resF 以在这些向量中创建重复的数据序列。

在您 运行 之后,您的仿函数使用按键转换来减少每个 36 元素试验的错误结果。

试一试,如果您遇到困难,我会提供一些额外的代码。