sched_getcpu不起作用

sched_getcpu doesn't work

本文关键字:不起作用 getcpu sched      更新时间:2023-10-16

我在谷歌云上有一个虚拟机,有一个16核、每个核2个线程的CPU插槽(超线程)。

这是lscpu:的输出

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                32
On-line CPU(s) list:   0-31
Thread(s) per core:    2
Core(s) per socket:    16
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 63
Stepping:              0
CPU MHz:               2300.000
BogoMIPS:              4600.00
Hypervisor vendor:     KVM
Virtualization type:   full
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              46080K
NUMA node0 CPU(s):     0-31

我在上面运行我的进程,并试图在不同的逻辑CPU之间分配线程。

unsigned num_cpus = std::thread::hardware_concurrency();
LOG(INFO) << "Going to assign threads to " << num_cpus << " logical cpus";
cpu_set_t cpuset;
int rc = 0;
for (int i = 0; i < num_cpus - 5; i++) {
    worker_threads.push_back(std::thread(&CalculationWorker::work, &(workers[i]), i));
    // Create a cpu_set_t object representing a set of CPUs. Clear it and mark
    // only CPU i as set.
    CPU_ZERO(&cpuset);
    CPU_SET(i, &cpuset);
    int rc = pthread_setaffinity_np(worker_threads[i].native_handle(),
            sizeof(cpu_set_t), &cpuset);
    if (rc != 0) {
        LOG(ERROR) << "Error calling pthread_setaffinity_np: " << rc << "n";
    }
    LOG(INFO) << "Set affinity for worker " << i << " to " << i;
}  

问题是num_cpus确实是32,但当我在每个正在运行的线程中运行以下代码行时:

LOG(INFO) << "Worker thread " << worker_number << " on CPU " << sched_getcpu();  

sched_getcpu()为所有线程返回0
这与这是一台虚拟机有关吗?

更新:
我发现pthread_setaffinity_np确实有效,显然有一些守护进程在后台运行,这就是为什么我看到其他核心被使用的原因
然而sched_getcpu仍然不能工作,并且在所有线程上都返回0,尽管我可以清楚地看到它们在不同的内核上运行。

你能试着在你的虚拟机上运行这个较小的程序吗:

#include <iostream>
#include <thread>
using namespace std;
int main(int argc, char *argv[])
{
    int rc, i;
    cpu_set_t cpuset;
    pthread_t thread;
    thread = pthread_self();
    //Check no. of cores on the machine
    cout << thread::hardware_concurrency() << endl;
    /* Set affinity mask */
    CPU_ZERO(&cpuset);
    for (i = 0; i < 8; i++) //I have 4 cores with 2 threads per core so running it for 8 times, modify it according to your lscpu o/p
        CPU_SET(i, &cpuset);
    rc = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
    if (rc != 0)
    cout << "Error calling pthread_setaffinity_np !!! ";
    /* Assign affinity mask to the thread */
    rc = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
    if (rc != 0)
    cout << "Error calling pthread_getaffinity_np !!!";
    cout << "pthread_getaffinity_np() returns:n";
    for (i = 0; i < CPU_SETSIZE; i++)
    {
        if (CPU_ISSET(i, &cpuset))
            {
            cout << " CPU " << i << endl;
            cout << "This program (main thread) is on CPU " << sched_getcpu() << endl; 
        }
    }
    return 0;
}

这将使您了解pthread_setaffinity_np是否在VM上工作。在虚拟机的情况下并没有这样的具体限制,相反,这可能是由于云上内核对某些进程的一些强制执行。你可以在这里阅读更多关于它的信息。

或者,尝试使用sched_setaffinity()来确认您是否真的能够在VM上设置cpusets。

我发现你的评论(当我将所有线程的亲和力设置为单个核心时,线程仍然在不同的核心上运行)和原始帖子的注释(sched_getcpu()对所有线程返回0)有点令人困惑。可能,这个0是为所有线程中的主线程(进程)返回的。