c/c++ epoll multithreading

c/c++ epoll multithreading

本文关键字:multithreading epoll c++      更新时间:2023-10-16

我知道关于这个问题有很多疑问,但我仍然找不到能帮助我的答案。

让我们以一个小型的带有epoll的tcp服务器为例,我们希望它利用尽可能多的cpu内核。我想了两种方法,但没有一种能很好地完成。

1 -每个线程都有自己的epoll fd,并且在"while(1)"循环中使用"epoll_wait()"来处理请求。

2 -只有一个epoll fd,并且在处理请求时为每个请求创建一个新线程。

在一个单线程中,我可以做大约25k req/s,所以我假设第一种方法会有很大帮助,但实际上,当我使用2 epoll fd时,应用程序只能处理~10k req/s。显然,我甚至没有考虑第二个方法是一个真正的方法,它意味着失败,所以是的。

所以基本上我的问题是:我应该如何实现多线程,所以它可以真的利用更多的cpu内核?

套接字是非阻塞的,TCP_NODELAY, TCP_FASTOPEN设置,并且我也使用了epolet模式。

要使用多个内核,您需要将进程划分为不同的线程,并让每个线程等待它自己的文件描述符。然而,在这种情况下,如果您只等待一个单个文件描述符,那么简单地多线程它并在每个文件描述符上使用阻塞读取可能会更有效。您还可以将不同的线程映射到不同的内核,因为调度器通常会尝试将不同的线程放在相同的内核上(因为它们的tlb是相同的),因此使用:

  int sched_setaffinity(pid_t pid,size_t cpusetsize,cpu_set_t *mask);

将帮助你分别仿射事物。显然,如果您的fd比cpu多,您将不得不做出权衡。

这就是我的想法:如果你有两个线程(就像你尝试过的那样)没有CPU限制,但在很大程度上等待I/O,调度器会认为"它们都有相同的TLB占用,并且都只是等待I/O -所以我就把它们都留在同一个CPU上"。这是一件合乎逻辑的事情,将提供良好的CPU和缓存性能,但您需要比这更少的延迟(因为粗略地说,OPS/sec = 1/latency)—所以使用上面的命令将这两个线程锁定到不同的内核—至少看看它做了什么。

请更具体地说明如何与您的第一个选项处理数据,fd(s)之间是否有任何数据同步?也许这就是降低整体性能的原因。

对于另一个选项,更合理的方法是使用1 epollfd并在多个线程中对其调用epoll_wait。这有点复杂,但对于绝对io绑定的应用程序可能会有更好的性能,因为fd(s)之间没有(或很少)数据依赖。