tbb::parallel_reduce 的 Lambda 形式:reduce 函数的第二个 rhs 参数中的常量
Lambda form of tbb::parallel_reduce: constness in second rhs argument of reduce function
我正在尝试使用 parallel_reduce:
并行构建直方图
#include "stdint.h"
#include "tbb/tbb.h"
#include <algorithm>
#include <vector>
#include <functional>
#include <iostream>
#include <numeric>
void buildhistogram(const uint8_t *inputImage, const size_t numElements, double *outputHist){
auto range = tbb::blocked_range<size_t>(0,numElements);
auto buildHistogramFcn = [&](const tbb::blocked_range<size_t>& r, const std::vector<double>& initHist){
std::vector<double> localHist(initHist);
for (size_t idx = r.begin(); idx != r.end(); ++idx){
localHist[inputImage[idx]]++;
}
return localHist;
};
auto reductionFcn = [&](const std::vector<double>& hist1, const std::vector<double>& hist2){
std::vector<double> histOut(hist1.size());
std::transform(hist1.begin(),hist1.end(),hist2.begin(),histOut.begin(),std::plus<double>());
return histOut;
};
std::vector<double> identity(256);
auto output = tbb::parallel_reduce(range, identity, buildHistogramFcn, reductionFcn);
std::copy(output.begin(),output.end(),outputHist);
}
我的问题涉及 parallel_reduce 的 lambda 形式的 Func 定义。如果您查看英特尔文档:
https://software.intel.com/en-us/node/506154
他们将 Func 的第二个 RHS 参数记录为常量:
Value Func::operator()(const Range& range, const Value& x)
但是,如果您查看他们的示例代码,他们定义了一个示例,其中第二个 RHS 是非常量,实际上他们修改 return 这个变量:
auto intelExampleFcn = [](const blocked_range<float*>& r, float init)->float {
for( float* a=r.begin(); a!=r.end(); ++a )
init += *a;
return init;
};
如果我尝试将变量 "initHist" 声明为非常量并直接使用此内存而不分配和 returning 本地副本:
auto buildHistogramFcn = [&](const tbb::blocked_range<size_t>& r, std::vector<double>& initHist){
for (size_t idx = r.begin(); idx != r.end(); ++idx){
initHist[inputImage[idx]]++;
}
return initHist;
};
我遇到一个编译错误:
/tbb/include/tbb/parallel_reduce.h:322:24: 错误:没有匹配函数来调用 'const (lambda at buildhistogramTBB.cpp:16:30)' 类型的对象
my_value = my_real_body(范围, const_cast(my_value));
我对 lambda 的第二个 RHS 参数实际上是否可以是非常量感兴趣,因为我希望能够避免将向量从 init 参数复制到局部变量我return.
是我误解了什么,还是英特尔的例子不正确?
Intel 示例中的第二个 "non-const" 参数是按值传递的。如果您要按值(而不是按引用)传递 initHist
向量,它也不需要 const
。 (当然,它会复制向量。但这似乎就是你正在做的事情。)
我正在尝试使用 parallel_reduce:
并行构建直方图#include "stdint.h"
#include "tbb/tbb.h"
#include <algorithm>
#include <vector>
#include <functional>
#include <iostream>
#include <numeric>
void buildhistogram(const uint8_t *inputImage, const size_t numElements, double *outputHist){
auto range = tbb::blocked_range<size_t>(0,numElements);
auto buildHistogramFcn = [&](const tbb::blocked_range<size_t>& r, const std::vector<double>& initHist){
std::vector<double> localHist(initHist);
for (size_t idx = r.begin(); idx != r.end(); ++idx){
localHist[inputImage[idx]]++;
}
return localHist;
};
auto reductionFcn = [&](const std::vector<double>& hist1, const std::vector<double>& hist2){
std::vector<double> histOut(hist1.size());
std::transform(hist1.begin(),hist1.end(),hist2.begin(),histOut.begin(),std::plus<double>());
return histOut;
};
std::vector<double> identity(256);
auto output = tbb::parallel_reduce(range, identity, buildHistogramFcn, reductionFcn);
std::copy(output.begin(),output.end(),outputHist);
}
我的问题涉及 parallel_reduce 的 lambda 形式的 Func 定义。如果您查看英特尔文档:
https://software.intel.com/en-us/node/506154
他们将 Func 的第二个 RHS 参数记录为常量:
Value Func::operator()(const Range& range, const Value& x)
但是,如果您查看他们的示例代码,他们定义了一个示例,其中第二个 RHS 是非常量,实际上他们修改 return 这个变量:
auto intelExampleFcn = [](const blocked_range<float*>& r, float init)->float {
for( float* a=r.begin(); a!=r.end(); ++a )
init += *a;
return init;
};
如果我尝试将变量 "initHist" 声明为非常量并直接使用此内存而不分配和 returning 本地副本:
auto buildHistogramFcn = [&](const tbb::blocked_range<size_t>& r, std::vector<double>& initHist){
for (size_t idx = r.begin(); idx != r.end(); ++idx){
initHist[inputImage[idx]]++;
}
return initHist;
};
我遇到一个编译错误:
/tbb/include/tbb/parallel_reduce.h:322:24: 错误:没有匹配函数来调用 'const (lambda at buildhistogramTBB.cpp:16:30)' 类型的对象 my_value = my_real_body(范围, const_cast(my_value));
我对 lambda 的第二个 RHS 参数实际上是否可以是非常量感兴趣,因为我希望能够避免将向量从 init 参数复制到局部变量我return.
是我误解了什么,还是英特尔的例子不正确?
Intel 示例中的第二个 "non-const" 参数是按值传递的。如果您要按值(而不是按引用)传递 initHist
向量,它也不需要 const
。 (当然,它会复制向量。但这似乎就是你正在做的事情。)