omp单一模拟通过c ++ 11

时间:2014-05-11 15:40:06

标签: c++ c++11 synchronization

我有多个std :: threads但只有一个应该执行一些任务(比如printf)(类似于pragma omp single)。

我试图修改semaphore code,但它并没有像我预期的那样工作。

#ifndef SEMAPHORE_H
#define SEMAPHORE_H

#include <mutex>
#include <condition_variable>
using namespace std;

class semaphore {
private:
    mutex mtx;
    condition_variable cv;
    int count, countMax;

public:
    semaphore(int count_ = 0):count(count_), countMax(count_){;}
    void notify()
    {
        unique_lock<mutex> lck(mtx);
        ++count;
        cv.notify_one();
    }
    void notifyAll()
    {
        unique_lock<mutex> lck(mtx);
        count = countMax;
        cv.notify_all();
    }

    bool wait()
    {
        unique_lock<mutex> lck(mtx);
        if (--count == 0) {
            return true;
        } else {
            cv.wait(lck, [this]() { return count > 0; });
            return false;
        }
    }
};

#endif // SEMAPHORE_H

主程序:

#include <iostream>
#include <vector>
#include <thread>
#include "semaphore.h"

semaphore sem(2);
int sum = 0;
std::mutex sumMutex;
int sumPrintAndReturn(int i)
{
    {
        std::lock_guard<std::mutex> lock(sumMutex);
        sum += i;
    }
    if (sem.wait()) {
        std::cout << "Sum (ONCE): " << sum << std::endl;
        sem.notifyAll();
    }
    std::cout << "Sum (EVERY): " << sum << std::endl;
    return sum;
}

int main()
{
    std::vector<std::thread> threads;
    for (int i = 0; i < 2; i++) {
        threads.push_back(std::thread(sumPrintAndReturn, i));
    }
    for (auto& thread: threads)
        thread.join();
    return 0;
}

问题是最终的总和是不同的。

Sum (EVERY): 0
Sum (ONCE): 1
Sum (EVERY): 1

那我为什么要谈论omp单身?这是我期望的一个例子和输出。

#include <iostream>
#include <omp.h>

int main()
{
    int sum = 0;
    int global_i = 0;
    #pragma omp parallel num_threads(2)
    {
        int i;
        #pragma omp critical
        i = global_i++;
        #pragma omp atomic
        sum += i;
        #pragma omp single
        printf("Sum (ONCE): %d\n", sum);
        printf("Sum (EVERY): %d\n", sum);
    }
}

输出:

Sum (ONCE): 1
Sum (EVERY): 1
Sum (EVERY): 1

我无法回答我的帖子,所以我会在这里发布最终和工作变体

#ifndef SEMAPHORE_H
#define SEMAPHORE_H

#include <mutex>
#include <condition_variable>
#include <atomic>
#include <functional>

class semaphore {
private:
    std::mutex mtx;
    std::condition_variable cv;
    std::atomic<int> count;
    const int countMax;
    bool flag;

    void releaseAll()
    {
        std::unique_lock<std::mutex> lck(mtx);
        flag = true;
        cv.notify_all();
        cv.wait(lck, [this]() { return !flag; });
    }

    bool wait()
    {
        std::unique_lock<std::mutex> lck(mtx);
        if (--count == 0) {
            count++;
            return false;
        }
        else {
            cv.wait(lck, [this]() { return flag; });
            count++;
            if (count == countMax) {
                flag = false;
                cv.notify_all();
            }
            cv.wait(lck, [this]() { return !flag; });
            return true;
        }
    }

public:
    semaphore(int count_ = 0) :count(count_), countMax(count_), flag(false){ }
    void runOnce(std::function<void()> func) {
        if (!wait()) {
            func();
            releaseAll();
        }
    }


};

#endif // SEMAPHORE_H

1 个答案:

答案 0 :(得分:1)

问题在于wait功能的实施。问题是您处理条件变量的方式...当您的信号量初始计数为2并且您运行两个线程时,[this]() { return count > 0; }将始终返回true

我在下面做了一个小改动,在那里我添加了一个新的布尔变量,该变量保持“成功”状态,该状态在最终“获胜”线程调用sem.wait()时设置。我不保证此代码的安全性或功能性;它只对我有用;)(VS2013快递)。

class semaphore {
private:
  mutex mtx;
  condition_variable cv;
  int count, countMax;
  bool flag;

public:
  semaphore(int count_ = 0) :count(count_), countMax(count_), flag(false){ ; }
  void notify()
  {
    unique_lock<mutex> lck(mtx);
    ++count;
    cv.notify_one();
  }
  void notifyAll()
  {
    unique_lock<mutex> lck(mtx);
    count = countMax;
    cv.notify_all();
  }

  bool wait()
  {
    unique_lock<mutex> lck(mtx);
    if (--count == 0) {
      flag = true;
      return true;
    }
    else {
      cv.wait(lck, [this]() { return flag; });
      return false;
    }
  }
};

示例输出:     总和(ONCE):1     总和(每个):1     总和(每个):1

注意:自从我回答这个问题以来,问题中的原始代码已经更改了。我的原始答案保持在完整性之下。


这个功能看起来非常可疑:

bool wait()
{
    unique_lock<mutex> lck(mtx);
    if (--count == 0) {
        return true;
    } else {
        cv.wait(lck, [this]() { return count > 0; });
    }
}

只有一个返回值!密切关注编译器警告会发现这一点。

$ g++ --std=c++11 -Wall semaphore.cpp
semaphore.cpp: In function ‘int sumPrintAndReturn(int)’:
semaphore.cpp:19:1: warning: no return statement in function returning non-void [-Wreturn-type]
In file included from semaphore.cpp:4:0:
semaphore.h: In member function ‘bool semaphore::wait()’:
semaphore.h:37:5: warning: control reaches end of non-void function [-Wreturn-type]