C ++:为快速的单一生产者多用户环境优化原子

时间:2016-10-01 07:56:16

标签: c++ multithreading atomic

我目前正在开展一个具有非常严格的循环和实时要求的项目。过早优化绝对不是一个恶习。我想尽可能地利用C ++原子的可能relaxed选项来实现我的目标。这是我的(线程不安全)设置:

// Shared data structure
uint8 data[100];
uint64 timeStamp = 0;

// Consumer threads 1...N run this
void loopConsume() {
    uint64 lastTimeStamp = 0;
    uint8 localData[100];
    for (;;) {
        while (timeStamp == lastTimeStamp);
        memcpy(localData, latestData.data, 100);
        lastTimeStamp = timeStamp;
        doSomething(localData);
    }
}

// Producer callback (singleton)
void produce(uint8 *newData) {
    memcpy(latestData.data, newData, 100);
    latestData.timeStamp++;
}

这是一个笨拙的(但表面上是正确的)尝试使用2个默认顺序一致性原子使其线程安全(和线程正确):

#include <atomic>

// Shared variables
uint8 data[100];
std::atomic<uint64> timeStamp = 0;
std::atomic<int32> numReaders = 0; // -1 means producer is writing

// Consumer threads 1...N run this
void loopConsume() {
    uint64 lastTimeStamp = 0;
    uint8 localData[100];
    for (;;) {
        uint64 t = timeStamp.load();
        while (t == lastTimeStamp) t = timeStamp.load();
        lastTimeStamp = t;
        for (;;) {
            int32 r = numReaders.load();
            if (r >= 0 && numReaders.compare_exchange_weak(r, r + 1))
                 break; 
        }
        memcpy(localData, data, 100);
        doSomething(localData);
        numReaders.fetch_sub(1);
    }
}

// Producer callback (singleton)
void produce(uint8 *newData) {
    while (!numReaders.compare_exchange_weak(0, -1));
    memcpy(data, newData, 100);
    timeStamp.fetch_add(1);
    numReaders.store(0);
}

如您所见,存在大量原子操作,默认情况下所有操作都使用顺序一致性。我相当肯定他们中的许多人都可以放松。但是哪些?我可以减少操作或简化设置吗?

另一个问题是争论。我希望读者很少,并且他们可以快速将数据复制到本地变量。那么有一个真正的优势是有一个类型的读写锁(如上所述),或只是一个常规的互斥锁?如果在这种情况下常规互斥锁速度更快,我能否以某种方式将其合并到时间戳原子变量中?

非常感谢!

0 个答案:

没有答案