linux - 为什么使用 taskset -c 时线程唤醒要快得多

标签 linux multithreading

在我的用例中我需要一个快速的线程唤醒机制。所以我写了一个简单的基准测试来看看信号量有多好。

#define PCALL(f)  \
  do {            \
    if (f == -1) { \
      perror(#f); \
      abort();    \
    }             \
  } while (0)

bool should_stop = false;

namespace semaphore_pthread{

struct Arg {
  sem_t start, stop;
} sems;

inline void SemInit(sem_t* sem) { PCALL(sem_init(sem, 0, 0)); }

inline void SemPost(sem_t* sem) { PCALL(sem_post(sem)); }

inline void SemWait(sem_t* sem) {
  int ret;
  do {
    ret = sem_wait(sem);
  } while (ret == -1 && errno == EINTR);
}

inline void SemDestroy(sem_t* sem) { PCALL(sem_destroy(sem));  }

void* StopperFunc(void *arg) {
  while (true) {
    SemWait(&sems.start);
    if (should_stop) break;
    SemPost(&sems.stop);
  }
  return nullptr;
}

int num_iters;
void* StarterFunc(void* arg) {
  pthread_t stopper;
  PCALL(pthread_create(&stopper, nullptr, &StopperFunc, nullptr));
  StartBenchmarkTiming();
  for (int i = 0; i < num_iters; ++i) {
    SemPost(&sems.start);
    SemWait(&sems.stop);
  }
  StopBenchmarkTiming();
  should_stop = true;
  SemPost(&sems.start);
  PCALL(pthread_join(stopper, nullptr));
  return nullptr;
}

void BM_Sem(int iters) {
  num_iters = iters;
  pthread_t starter;
  PCALL(pthread_create(&starter, nullptr, &StarterFunc, nullptr));
  PCALL(pthread_join(starter, nullptr));
}

这只是两个线程在做乒乓球一样醒来。每次迭代包括两次唤醒。

在我的机器上(Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz),每次迭代大约需要 5us。我也尝试过 eventfd 和 futex,但它们提供了相似的结果。但是,如果使用 taskset -c 1(所有线程都运行在 CPU 1 中),它只需要 1.5 us。这背后的原因是什么?有没有办法以编程方式实现相同的效果,而不是依赖于任务集?

最佳答案

要使用 C 而不是 taskset 程序将您的进程绑定(bind)到单个核心,您可以使用 sched_setaffinity .

至于为什么将两个线程放在一个内核上会更快,可能有以下几点:

  1. 两个独立的核心具有独立的缓存,需要复制一些相同的信息。
  2. 系统上的其他任务可能会相互竞争,弄脏缓存。
  3. 两个内核可能位于两个独立的物理处理器上,需要插槽间通信。
  4. 当只有一个内核处于事件状态时,它更有可能在 Intel 处理器上进入“turbo”模式,而绝不会进入休眠模式。

关于linux - 为什么使用 taskset -c 时线程唤醒要快得多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36973230/

相关文章:

java - 无法访问线程 run() 中的方法

java - 监视 Java 应用程序上的锁争用

multithreading - Delphi并行编程-多线程速度慢

java - 重用 java.util.Random 实例与每次都创建一个新实例

linux - Ghostscript 结合 PDfs 和多线程/核心

linux - 如何禁用 X (Xlib) 中的自动鼠标中键事件?

c - 寻找一种在 C 中访问 C++ 对象的方法,就像我在 C++ 中一样

c++ - 更改全局变量名称

linux - user::rw- 中的 "::"是什么意思

python - 用于编辑从 numpy savez 函数生成的 zip 文件的 Linux 命令