Barrier class 分而治之(忙时销毁互斥体)C++
Barrier class with divide and conquer (mutex destroyed while busy) C++
我已经尝试实施障碍 class。我想使用分而治之算法对此进行测试。我的class定义如下:
class barrier{
private:
mutex mtx;
condition_variable cv;
atomic<int> counter;
atomic<int> waiting;
atomic<int> thread_count;
public:
barrier(int count) : thread_count(count), counter(0), waiting(0) {}
void wait()
{
//fence mechanism
unique_lock<mutex> lock(mtx);
++counter;
++waiting;
cv.wait(lock, [&] {return counter >= thread_count; });
--waiting;
if (waiting == 0) counter = 0;
for (int i = 0; i < thread_count; ++i) cv.notify_one();
lock.unlock();
}
};
关于分治算法,我是这样实现的:
int main() {
vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
int n = size(v)/2;
while (n >= 1) {
dnc_light(v, n);
n /= 2;
}
return 0;
}
void dnc_light (vector<int> &v, int n) {
thread trd[50];
barrier bar(n);
for (int i = 0; i < n; ++i) {
trd[i] = thread([&] {
v[i] += v[i + n];
bar.wait();
});
}
}
然而,这会导致 "mutex destroyed while busy" - 错误。怎么来的?我需要动态处理 barrier bar(...)
的大小。
This however results in a "mutex destroyed while busy" - error. How come?
dnc_light
使用对本地 barrier
对象的引用创建多个线程。然后函数 returns 破坏了那个局部 barrier
那些线程仍在使用,这导致 "mutex destroyed while busy" 错误。
此外,线程是可连接的,因此它们的析构函数将抛出异常,因为它们既没有连接也没有分离。
解决方法是在从函数返回之前加入线程:
void dnc_light(vector<int> &v, int n) {
vector<thread> trd(n);
barrier bar(n);
for (int i = 0; i < n; ++i) {
trd[i] = thread([&](){
v[i] += v[i + n];
bar.wait();
});
}
for(auto& t : trd)
t.join();
}
在上面的代码中,你根本不需要屏障,因为这个连接循环一直等到所有线程终止。
barrier
中的变量不需要是原子的,因为它只在持有互斥锁时访问它们。简化:
class barrier {
mutex mtx;
condition_variable cv;
int const thread_count;
int counter{0};
int waiting{0};
public:
barrier(int count) : thread_count(count) {}
void wait() {
unique_lock<mutex> lock(mtx);
++counter;
++waiting;
cv.wait(lock, [&](){
return counter >= thread_count;
});
if(waiting == thread_count)
cv.notify_all();
if(!--waiting)
counter = 0;
}
};
我已经尝试实施障碍 class。我想使用分而治之算法对此进行测试。我的class定义如下:
class barrier{
private:
mutex mtx;
condition_variable cv;
atomic<int> counter;
atomic<int> waiting;
atomic<int> thread_count;
public:
barrier(int count) : thread_count(count), counter(0), waiting(0) {}
void wait()
{
//fence mechanism
unique_lock<mutex> lock(mtx);
++counter;
++waiting;
cv.wait(lock, [&] {return counter >= thread_count; });
--waiting;
if (waiting == 0) counter = 0;
for (int i = 0; i < thread_count; ++i) cv.notify_one();
lock.unlock();
}
};
关于分治算法,我是这样实现的:
int main() {
vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
int n = size(v)/2;
while (n >= 1) {
dnc_light(v, n);
n /= 2;
}
return 0;
}
void dnc_light (vector<int> &v, int n) {
thread trd[50];
barrier bar(n);
for (int i = 0; i < n; ++i) {
trd[i] = thread([&] {
v[i] += v[i + n];
bar.wait();
});
}
}
然而,这会导致 "mutex destroyed while busy" - 错误。怎么来的?我需要动态处理 barrier bar(...)
的大小。
This however results in a "mutex destroyed while busy" - error. How come?
dnc_light
使用对本地 barrier
对象的引用创建多个线程。然后函数 returns 破坏了那个局部 barrier
那些线程仍在使用,这导致 "mutex destroyed while busy" 错误。
此外,线程是可连接的,因此它们的析构函数将抛出异常,因为它们既没有连接也没有分离。
解决方法是在从函数返回之前加入线程:
void dnc_light(vector<int> &v, int n) {
vector<thread> trd(n);
barrier bar(n);
for (int i = 0; i < n; ++i) {
trd[i] = thread([&](){
v[i] += v[i + n];
bar.wait();
});
}
for(auto& t : trd)
t.join();
}
在上面的代码中,你根本不需要屏障,因为这个连接循环一直等到所有线程终止。
barrier
中的变量不需要是原子的,因为它只在持有互斥锁时访问它们。简化:
class barrier {
mutex mtx;
condition_variable cv;
int const thread_count;
int counter{0};
int waiting{0};
public:
barrier(int count) : thread_count(count) {}
void wait() {
unique_lock<mutex> lock(mtx);
++counter;
++waiting;
cv.wait(lock, [&](){
return counter >= thread_count;
});
if(waiting == thread_count)
cv.notify_all();
if(!--waiting)
counter = 0;
}
};