gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 12:51:46 24 4
gpt4 key购买 nike

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

#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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com