如何正确实现三重缓冲? [英] How to correctly implement triple buffering?
问题描述
我正在尝试模拟视频卡(生产者线程)和监视器(消费者线程),以了解在教育方面发生了什么.所以这是技术任务说明:
I am trying to simulate videocard (producer thread) and a monitor(consumer thread), to figure out what is going on in educational purposes. So here is the technical task description:
生产者线程以 1000 fps 的速度生成帧像素数据.消费者线程以 60 fps 的速度运行,并且每一帧都必须至少有 1/60 秒的时间访问最后生成的帧.为简单起见,每个帧都由一些 int*
表示.
Producer thread produces frames pixel data at 1000 fps. Consumer thread runs at 60 fps and every frame it must have access to last produced frame for at least 1/60th of second. Each frame is represented by some int*
, for simplicity.
所以我的解决方案是我有 2 个指针数组:一个用于生产者,一个用于消费者.再加上一些空闲的、未使用的指针,在任何给定的时间都不属于消费者或生产者.
So my solution is that i have array of 2 pointers: one for producer, one for consumer. And plus some free, unused pointer, which is not owned by consumer or producer at any given moment of time.
#define Producer 0
#define Consumer 1
int* usedPointers[2];
std::atomic<int*> freePointer;
producer 总是将帧像素写入
usedPointers[Producer]
,然后usedPointers[Producer] = freePointer.exchange(usedPointers[Producer], memorySemanticsProducer);
所以最后一个完整生成的帧现在由freePointer
指向,并且可以自由写入新帧,而不是破坏最后一个实际完整帧.producer always writes frame pixels to
usedPointers[Producer]
, then doesusedPointers[Producer] = freePointer.exchange(usedPointers[Producer], memorySemanticsProducer);
so that last completely produced frame is now pointed byfreePointer
, and its free to write new frame, not destroying last actual complete frame.consumer 做了
usedPointers[Consumer] = freePointer.exchange(usedPointers[Consumer], memorySemanticsConsumer);
以便它拥有最后的实际帧数据,然后可以自由访问usedPointers[Consumer]
只要它愿意.consumer does
usedPointers[Consumer] = freePointer.exchange(usedPointers[Consumer], memorySemanticsConsumer);
so that it would own last actual frame data, and then is free to accessusedPointers[Consumer]
as long, as it desires to.如果我错了,请纠正我.
Correct me if i am wrong.
我想念什么是
memorySemanticsXXX
.有描述 但我不知道我应该在每个线程中使用哪个为什么.所以我想就此寻求一些提示.I miss what is
memorySemanticsXXX
. There are descriptions but i cannot figure out which exactly should i use in every thread and why. So i am asking for some hints on that.推荐答案
memorySemanticsXXX
您提到的是围绕exchange()
行的其余代码.std::atomic::exchange()
的默认行为是使用memory_order_seq_cst
(exchange()
的第二个参数是不使用).memorySemanticsXXX
you're mentioning are about the rest of your code surrounding theexchange()
lines. The default behavior forstd::atomic::exchange()
is thatmemory_order_seq_cst
is used (the second parameter forexchange()
you're not using).这同时意味着三件事:
- 您在
exchange()
调用之前编写的任何代码都保证在该调用之前执行(否则编译器优化会重新排序您的代码)并且该执行的结果将在调用exchange()
之前在所有其他线程中可见(CPU 缓存传播). 与之前相同,但针对您在
exchange()
行之后编写的代码.
- Any code you wrote before your
exchange()
call is guaranteed to execute before that call (otherwise compiler optimizations can reorder your code) and the results of that execution will be visible in all other threads (CPU cache propagation) before theexchange()
call is made. The same as previous but for the code you wrote after your
exchange()
line.
exchange()
调用前后的所有代码都按照您编写的确切顺序执行(包括其他原子操作).All of the code before and after
exchange()
call is executed in the exact order you wrote it (including other atomic operations).所以,重点是您可以选择不设置这些限制中的一个、两个或所有三个,这可以为您带来速度提升.您不应该为此烦恼除非您遇到性能瓶颈.如果没有瓶颈,那么只需使用
std::atomic
而不带第二个参数(它将采用默认值).So, the whole point is that you may choose not to have one, two or all three of these restrictions, which can bring you speed improvements. You shouldn't bother with this unless you have a performance bottleneck. If there's no bottleneck then just use
std::atomic
without the second parameter (it will take the default value).如果您不使用所有三个限制,则必须非常小心地编写代码,否则可能会意外崩溃.
In case you don't use all three restrictions you have to be really careful writing your code otherwise it can unpredictably crash.
在此处阅读更多相关信息:内存顺序
Read more about it here: Memory order
这篇关于如何正确实现三重缓冲?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- 您在