Multithreading 带分治的屏障类(忙时互斥被破坏)C++;
我尝试过实现一个barrier类。我想用分治算法来测试这个。我的班级定义如下:Multithreading 带分治的屏障类(忙时互斥被破坏)C++;,multithreading,c++11,barrier,Multithreading,C++11,Barrier,我尝试过实现一个barrier类。我想用分治算法来测试这个。我的班级定义如下: class barrier{ private: mutex mtx; condition_variable cv; atomic<int> counter; atomic<int> waiting; atomic<int> thread_count; public: barrier(int count) : thread_count
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();
});
}
}
等级壁垒{
私人:
互斥mtx;
条件变量cv;
原子计数器;
原子等待;
原子线程计数;
公众:
屏障(整数计数):线程计数(计数),计数器(0),等待(0){
无效等待()
{
//围栏机制
唯一锁(mtx);
++计数器;
++等待;
等待(锁,[&]{返回计数器>=线程计数;});
--等待;
如果(等待==0)计数器=0;
对于(int i=0;i
至于分治算法,我实现了如下:
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();
});
}
}
intmain(){
向量v={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int n=尺寸(v)/2;
而(n>=1){
dnc_灯(v,n);
n/=2;
}
返回0;
}
无效dnc_灯(矢量和v,内部n){
螺纹trd[50];
栅栏(n);
对于(int i=0;i
但是,这会导致“忙时互斥被破坏”错误。怎么会?我需要动态处理障碍条(…)
的大小
但是,这会导致“忙时互斥被破坏”错误。为什么
dnc\u light
创建多个线程,并引用本地屏障
对象。然后函数返回销毁那些线程仍在使用的本地屏障,这会导致“忙时销毁互斥锁”错误
此外,线程是可连接的,因此它们的析构函数将抛出异常,因为它们既没有连接也没有分离
修复方法是在从函数返回之前加入线程:
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();
}
但是,这会导致“忙时互斥被破坏”错误。为什么
dnc\u light
创建多个线程,并引用本地屏障
对象。然后函数返回销毁那些线程仍在使用的本地屏障,这会导致“忙时销毁互斥锁”错误
此外,线程是可连接的,因此它们的析构函数将抛出异常,因为它们既没有连接也没有分离
修复方法是在从函数返回之前加入线程:
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();
}
我刚刚测试了它,你的建议很有效。我有两个问题:我能在dnc_light
中分离线程而不是连接它们吗?昨天,我尝试在主函数中对所有内容进行编码,但这导致了相同的错误-是因为在for循环之后屏障被破坏了吗?@SAFD您可以分离线程以避免加入它们。但是,在这种情况下,必须确保屏障保持活动。一种方法是autobarrier=make_shared(n)代码>并通过值将barrier
智能指针传递到线程,以便它在使用时保持活动状态。好吧,恐怕这对我来说太复杂了。经过进一步的测试,我注意到总数并不总是136。有时线程会把计算搞得一团糟。因此,我更改了dnc_light
:现在它捕获了v
byval,并有一个向量temp
,将总和保存到该向量上。这在一定程度上解决了这个问题。我现在得到的唯一错误是,一些随机和结果是0
——但并不总是如此。@SAFD发生这种情况的原因可能是多个线程同时修改同一个向量,这是一种竞争条件。我刚刚测试了它,您的建议也起了作用。我有两个问题:我能在dnc_light
中分离线程而不是连接它们吗?昨天,我尝试在主函数中对所有内容进行编码,但这导致了相同的错误-是因为在for循环之后屏障被破坏了吗?@SAFD您可以分离线程以避免加入它们。但是,在这种情况下,必须确保屏障保持活动。一种方法是autobarrier=make_shared(n)代码>并通过值将barrier
智能指针传递到线程,以便它在使用时保持活动状态。好吧,恐怕这对我来说太复杂了。经过进一步的测试,我注意到总数并不总是136。有时线程会把计算搞得一团糟。因此,我更改了dnc_light
:现在它捕获了v
byval,并有一个向量temp
,将总和保存到该向量上。这在一定程度上解决了这个问题。我现在得到的唯一错误是,一些随机和最终为0
——但并不总是如此。@SAFD这可能是因为多个线程同时修改同一个向量,这是一种竞争条件。