C++ 如何消除并行std::transform_reduce()的中间容器?
通常,我必须找到C++ 如何消除并行std::transform_reduce()的中间容器?,c++,multithreading,concurrency,stl,c++20,C++,Multithreading,Concurrency,Stl,C++20,通常,我必须找到Sum(f(I),1,N)或乘积(f(I),1,N),其中f(I)在计算上是CPU密集型的,而积分I来自顺序范围,但很大 使用C++20编译器,我可以编写以下函数: uint64_t solution(uint64_t N) { std::vector<uint64_t> v(N); std::iota(v.begin(), v.end(), 1ULL); return std::transform_reduce(
Sum(f(I),1,N)
或乘积(f(I),1,N)
,其中f(I)
在计算上是CPU密集型的,而积分I来自顺序范围,但很大
使用C++20编译器,我可以编写以下函数:
uint64_t solution(uint64_t N)
{
std::vector<uint64_t> v(N);
std::iota(v.begin(), v.end(), 1ULL);
return std::transform_reduce(
std::execution::par,
v.cbegin(), v.cend(),
0ull,
std::plus<>(),
[]f(const uint64_t& i)->uint64_t {
uint64_t result(0);
// expensive computation of result=f(i) goes here
// ...
return result;
});
}
uint64\t解决方案(uint64\t N)
{
std::向量v(N);
标准::物联网(v.begin()、v.end()、1ULL);
返回std::transform\u reduce(
标准::执行::标准杆,
v、 cbegin(),v.cend(),
乌尔,
std::plus(),
[]f(常数uint64\u t&i)->uint64\u t{
uint64_t结果(0);
//结果=f(i)的昂贵计算在这里进行
// ...
返回结果;
});
}
但这将受到RAM限制
如何在运行时仅使用C++20 STL(即,没有特定于供应商或第三方的库)完全消除带有输入向量的中间内存操作,同时又能高效地并行执行?免责声明:我以前没有在C++20中实现迭代器的经验 这似乎适用于GCC10.1和
-std=c++2a
。我在很短的时间内完成了这项工作,没有花太多的心思,因此实现肯定可以得到改进,只要将其模板化即可。如果将操作符
替换为旧的双向比较操作符,那么它也应该使用C++17运行,但我还没有测试它。如果您发现任何错误或易于纠正的设计缺陷,欢迎您在下面对其进行评论,以便改进此答案
#包括
#如果cplusplus>201703L
#包括
#恩迪夫
#包括
#包括
#包括
#包括
类计数迭代器{
公众:
typedef std::ptrdiff_t difference_type;
typedef std::ptrdiff_t value_type;
typedef空指针;
类型定义无效引用;
typedef std::随机访问迭代器标记迭代器类别;
私人:
值类型val{0};
公众:
计数迭代器()=默认值;
显式计数迭代器(value_type init)noexcept:val_{init}{
值类型运算符*()常量noexcept{return val;}
值类型运算符[](差异类型索引)常量noexcept{
返回值+索引;
}
计数迭代器和运算符++()无异常{
++瓦卢;
归还*这个;
}
计数迭代器运算符++(int)noexcept{
计算迭代器res{*this};
++(*本条);
返回res;
}
计数迭代器和运算符--()无异常{
--瓦卢;
归还*这个;
}
计数迭代器运算符--(int)noexcept{
计算迭代器res{*this};
--(*本条);
返回res;
}
友元计数迭代器运算符+(计数迭代器常量&it,
差异(类型常量和偏移量)无例外;
友元计数迭代器运算符+(差分类型常量和偏移量,
计数迭代器常数&it)无异常;
友元计数迭代器运算符-(计数迭代器常量&it,
差异(类型常量和偏移量)无例外;
友元差分类型运算符-(计数迭代器常量&a,
计数迭代器常数&b)无异常;
计数迭代器和运算符+=(差分类型偏移量)无异常{
val_+=偏移量;
归还*这个;
}
计数迭代器和运算符-=(差分类型偏移量)无异常{
val_u-=偏移量;
归还*这个;
}
friend bool运算符==(计数迭代器常量&a,
计数迭代器常数&b)无异常;
#如果cplusplus>201703L
friend std::强排序运算符(计数迭代器常量&a,
计数(迭代器常数&b);
#否则
friend bool运算符!=(计数迭代器常量&a,
计数迭代器常数&b)无异常;
friend bool运算符=(计数迭代器常量&a,
计数迭代器常数&b)无异常;
friend bool运算符(计数迭代器常数&a,
计数迭代器常数&b)无异常;
#恩迪夫
};
计数迭代器
运算符+(计数迭代器常数&it,
计数迭代器::差异类型常量和偏移量)无异常{
返回计数迭代器{it.val}+offset};
}
计数迭代器运算符+(计数迭代器::差分类型常量和偏移量,
计数(迭代器常数&it)无异常{
返回计数迭代器{it.val}+offset};
}
计数迭代器
运算符-(计数迭代器const&it,
计数迭代器::差异类型常量和偏移量)无异常{
返回计数迭代器{it.val{uu-offset};
}
计数迭代器::差异类型
运算符-(计数迭代器常量&a,计数迭代器常量&b)无例外{
返回a.val \-b.val \;
}
布尔运算符==(计数迭代器常数&a,
计数(迭代器常数&b)无例外{
返回a.val==b.val;
}
#如果cplusplus>201703L
std::强排序运算符(计数迭代器常数&a,
计数(迭代器常数&b){
返回a.val ub.val;
}
#否则
接线员=(计算迭代器常数&a,
计数(迭代器常数&b)无例外{
返回a.val!=b.val;
}
布尔运算符=b.val_u2;;
}
布尔运算符(计数迭代器常数&a,
计数(迭代器常数&b)无例外{
返回a.val>b.val;
}
#恩迪夫
int main(){
自动恢复=标准::转换\u减少(
标准::执行::标准杆,
计数迭代器(0),计数迭代器(10),
0升,
std::plus(),
[](const std::ptrdiff_t&i){return i*i;});
std::cout经过一些按摩和实验后,我确认双向迭代器,基于上面Paul的样本,已经工作:
class counting_iterator {
public:
using iterator_category = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = std::ptrdiff_t;
private:
value_type val_;
public:
counting_iterator() : val_(0) {}
explicit counting_iterator(value_type init) : val_(init) {}
value_type operator*() noexcept { return val_; }
const value_type& operator*() const noexcept { return val_; }
counting_iterator& operator++() noexcept { ++val_; return *this; }
counting_iterator operator++(int) noexcept { counting_iterator res{ *this }; ++(*this); return res; }
counting_iterator& operator--() noexcept { --val_; return *this; }
counting_iterator operator--(int) noexcept { counting_iterator res{ *this }; --(*this); return res; }
value_type operator[](difference_type index) noexcept { return val_ + index; }
counting_iterator& operator+=(difference_type offset) noexcept { val_ += offset; return *this; }
counting_iterator& operator-=(difference_type offset) noexcept { val_ -= offset; return *this; }
counting_iterator operator+(difference_type offset) const noexcept { return counting_iterator{ *this } += offset; };
/*counting_iterator& operator+(difference_type offset) noexcept { return operator+=(offset); }*/
counting_iterator operator-(difference_type offset) const noexcept { return counting_iterator{ *this } -= offset; };
/*counting_iterator& operator-(difference_type offset) noexcept { return operator-=(offset); }*/
difference_type operator-(counting_iterator const& other) noexcept { return val_ - other.val_; }
bool operator<(counting_iterator const& b) const noexcept { return val_ < b.val_; }
bool operator==(counting_iterator const& b) const noexcept { return val_ == b.val_; }
bool operator!=(counting_iterator const& b) const noexcept { return !operator==(b); }
std::strong_ordering operator<=>(counting_iterator const& b) const noexcept { return val_ <=> b.val_; }
};
类计数迭代器{
公众:
使用迭代器\u category=std::双向迭代器\u标记;
使用差分类型=std::ptrdiff\t;
使用value_type=std::p