为STL算法(例如std::execution::par)指定std::for_each执行策略时,如何使用迭代器?

在下面的示例中,我希望采用Eigen3矩阵对角线的平方根:

template<typename T>
using Matrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;

template<typename T>
std::vector<T> getStdDev(const Matrix &x) const {
    const size_t len = x.rows();
    std::vector<T> stdDev(len);

    // Generate indices.
    size_t idx = 0;
    std::vector<size_t> indices(len);
    auto ind = [&idx]() {
        return idx++;
    };
    std::generate(indices.begin(), indices.end(), ind);

    // Take square root of diagonal elements.
    auto sr = [&x](size_t i) {
        stdDev[i] = std::sqrt(x(i, i));
    };
    std::for_each(std::execution::par, indices.begin(), indices.end(), sr);

    return stdDev;
}

据我所知,以上代码是线程安全的。但是,如何在没有首先生成所需索引的情况下,以线程安全的方式使用Iterator达到相同的效果?假定要迭代的容器没有实现Iterator,或者没有线程安全的Iterator。

理想情况下,我希望以一般方式进行此操作(我知道Eigen具有Iterators,此处仅出于示例目的使用它)。

另外,最好只使用C++功能(不使用库,但使用任何非草稿标准)。

最佳答案

您可以使用 boost::counting_iterator ranges::view::iota 之类的东西

template<typename T>
std::vector<T> getStdDev(const Matrix &x) const {
    const size_t len = x.rows();
    std::vector<T> stdDev(len);

    // Take square root of diagonal elements.
    auto sr = [&x](size_t i) {
        return std::sqrt(x(i, i));
    };
    std::transform(std::execution::par, boost::counting_iterator<int>(0), boost::counting_iterator<int>(len), stdDev.begin(), sr);

    return stdDev;
}

自己实现counting_iterator并不难,指定RandomAccessIterator的所有必需成员只是一件繁琐的事情。
class counting_iterator
{
public:
    typedef size_t value_type;
    typedef const size_t& reference;
    typedef const size_t* pointer;
    typedef ptrdiff_t difference_type;
    typedef random_access_iterator_tag iterator_category;

    explicit counting_iterator(size_t x);
    size_t const& base() const { return m_inc; }
    reference operator*() const { return m_inc; }
    counting_iterator& operator++() { ++m_inc; return *this; }
    counting_iterator& operator--() { --m_inc; return *this; }

    counting_iterator& operator+=(size_t i) { m_inc += i; return *this; }
    counting_iterator& operator-=(size_t i) { m_inc -= i; return *this; }

    // and loads of others
private:
    size_t m_inc;
};

07-24 09:44
查看更多