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