Multithreading 带分治的屏障类(忙时互斥被破坏)C++;

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

我尝试过实现一个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(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这可能是因为多个线程同时修改同一个向量,这是一种竞争条件。