在为std::execution::par
之类的STL算法指定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,或者没有线程安全的迭代器。
理想情况下,我希望以一般方式进行此操作(我知道Eigen具有Iterators,在此仅用于示例目的)。
此外,最好只使用C ++功能(没有库,但有任何非草稿标准)。
答案 0 :(得分:0)
您可以使用类似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;
};