简体   繁体   English

如何避免多线程应用程序中的缓存数据 C++

[英]How to avoid cached data in multithread application C++

Can someone clarify the next moment.有人可以澄清下一刻。 I saw some implementations of std::queue for multithreading purposes, where all operations of pushing/poping/erasing elements where protected with mutex, but when I see that I imagine next scenario: we have two threads (thread1 and thread2) and they are running on different cores of the processor, thus they have different L1 caches.我看到了一些用于多线程目的的 std::queue 实现,其中推/弹出/擦除元素的所有操作都受互斥锁保护,但是当我看到我想象下一个场景时:我们有两个线程(线程 1 和线程 2),它们是在处理器的不同内核上运行,因此它们具有不同的 L1 缓存。 And we have the next queue:我们有下一个队列:

struct Message {
    char* buf;
    size_t size;
};
std::queue<Message> messageQueue;

Thread1 adds some element to queue, then thread2 tries to access an element with front() method, but what if that piece of memory was previosly cached for this core of the processor (so the size variable may not indicate current size of buf variable, or buf pointer may hold wrong (not updated) address)? Thread1 将一些元素添加到队列中,然后 thread2 尝试使用 front() 方法访问一个元素,但是如果该 memory 已预先为处理器的此内核缓存怎么办(因此 size 变量可能不表示 buf 变量的当前大小,或 buf 指针可能持有错误(未更新)的地址)? I have such problem while designing client/server application on the server side.我在服务器端设计客户端/服务器应用程序时遇到了这样的问题。 In my app server is running in one thread, it works directly with sockets, and when it receives new message, it allocates memory for that message and adds this message to some message queue, then other thread accesses this queue, processes message and then deletes it.在我的应用服务器在一个线程中运行,它直接与 sockets 一起工作,当它接收到新消息时,它为该消息分配 memory 并将该消息添加到某个消息队列中,然后其他线程访问该队列,处理消息然后删除它。 I am always afraid of caching problems, and because of that I have created my own implementation of queue with volatile pointers.我总是害怕缓存问题,因此我创建了自己的带有可变指针的队列实现。 What is the proper way to work with such things?处理这些事情的正确方法是什么? Do I have to avoid using std::list, std::queue with locks?我必须避免使用带锁的 std::list、std::queue 吗? If this problem is impossible, could you please explain why?如果这个问题是不可能的,你能解释一下为什么吗?

It's not your problem.这不是你的问题。 You're writing C++ code.您正在编写 C++ 代码。 It's the compiler's job to ensure your code makes the CPU and its caches do the right thing, not yours.编译器的工作是确保你的代码让 CPU 和它的缓存做正确的事,而不是你的。 You just have to comply with the rules for whatever threading standard you are using.您只需要遵守您使用的任何线程标准的规则。

But if i lock some mutex, how can i be shure, that this memory isn't cached, or mutex locking somehow guarantee reading directly from the memory?但是,如果我锁定了一些互斥体,我怎么能确定这个 memory 没有被缓存,或者互斥体锁定以某种方式保证直接从 memory 读取?

You can't.你不能。 And that's a good thing.这是一件好事。 Caching massively improves performance and main memory is terribly slow.缓存极大地提高了性能,主 memory非常慢。 Fortunately, no modern CPU that you're likely to write multi-threaded code on requires you to sacrifice performance like that.幸运的是,您可能会在其上编写多线程代码的现代 CPU 不会要求您牺牲这样的性能。 They have incredibly sophisticated optimizations such as cache coherency hardware and prefetch pinning to avoid things that hurt performance that much.它们具有令人难以置信的复杂优化,例如缓存一致性硬件和预取固定,以避免严重损害性能的事情。 What you want is for your code to work, not for it to work awfully.你想要的是让你的代码工作,而不是让它工作得非常糟糕。

You can safely use mutex locking as long as you use it everywhere you MIGHT access / update in a threaded fashion.只要您在可能以线程方式访问/更新的任何地方使用它,您就可以安全地使用互斥锁。 This means for this example that adding to / removing from / parsing your list is mutex-guarded.这意味着对于这个示例,添加/删除/解析您的列表是互斥保护的。

You also have to be careful that the objects you're storing in your queue are properly protected.您还必须小心,您存储在队列中的对象受到适当保护。

Also, please please please do not use char *.另外,请不要使用char *。 That's what std::string is for.这就是 std::string 的用途。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM