有没有办法在C++中制作无锁"counter"随机访问迭代器?

Is there a way of making a lock-free "counter" random access iterator in C++?

本文关键字:counter 随机 访问 迭代器 C++ 有没有      更新时间:2023-10-16

我正在试验一个玩具问题的执行策略,即在给定其系数和评估点 (x) 的情况下,在某个点评估多项式。

这是我的实现:

class counter: public std::iterator<
std::random_access_iterator_tag,   // iterator_category
size_t,                      // value_type
size_t,                      // difference_type
const size_t*,               // pointer
size_t                       // reference
>{
size_t num = 0;
public:
explicit counter(size_t _num) : num(_num) {}
counter& operator++() {num += 1; return *this;}
counter operator++(int) {counter retval = *this; ++(*this); return retval;}
bool operator==(counter other) const {return num == other.num;}
bool operator!=(counter other) const {return !(*this == other);}
counter& operator+=(size_t i) { num += i; return *this; }
counter& operator-=(size_t i) { num -= i; return *this; }
counter operator +(counter &other) const { return counter(num + other.num);}
counter operator -(counter &other) const { return counter(num - other.num); }
counter operator +(size_t i) const { return counter(num + i); }
counter operator -(size_t i) const {return counter(num - i); }
reference operator*() const {return num;}
};

double better_algorithm_polinomials(const vector<double> & coeffs, double x) {
return transform_reduce(execution::par, cbegin(coeffs), end(coeffs), counter(0), 0.0, plus{}, [x](double coeff, size_t index) { return coeff * pow<double>(x, index); });
}

这适用于 par 策略,但对于par_unseq,由于竞争条件,这失败了。

我试图使用 atomic_size_t 来缓解它们,但有些地方(例如复制构造或 ++(int) 运算符),我不是原子的,可能必须使用锁......我想知道是否有更好的方法。

这不起作用:

class counter: public std::iterator<
std::random_access_iterator_tag,   // iterator_category
atomic_size_t,                      // value_type
atomic_size_t,                      // difference_type
const atomic_size_t*,               // pointer
atomic_size_t                       // reference
>{
atomic_size_t num = 0;
public:
explicit counter(size_t _num) : num(_num) {}
counter(counter &other) {  num = other.num.load();}
counter& operator++() {num += 1; return *this;}
const counter operator++(int) {num += 1; return counter(num-1);}
bool operator==(counter &other) const {return num == other.num;}
bool operator!=(counter &other) const {return !(*this == other);}
counter& operator+=(size_t i) { num += i; return *this; }
counter& operator-=(size_t i) { num -= i; return *this; }
counter operator +(counter &other) const { return counter(num + other.num);}
difference_type operator -(counter &other) const { return num - other.num; }
counter operator +(size_t i) const { return counter(num + i); }
difference_type operator -(size_t i) const {return num - i; }
size_t operator [](size_t i) const {return i;}
reference operator*() const {return num.load();}
};

我试图使用atomic_size_t来缓解它们

请注意,您应该静态断言std::atomic<std::size_t>在您的平台中实际上是无锁的。

但是有些地方(例如复制构造或++(int)运算符),我不是原子的,可能必须使用锁...

使用非顺序执行策略时无法获取锁!参见[算法.parallel],例如这个和这个。