如何将一个进程(线程)绑定到一个固定的CPU核上?——004

http://blog.youkuaiyun.com/sangyongjia/article/details/50725734


As multi-core CPUs become increasingly popular on server-grade hardware as well as end-user desktop PCs or laptops, there have been growing efforts in the community (e.g., in terms of programming models, compiler or operating system support) towards developing applications optimized for multi-core architecture.

One operating system (OS) support often exploited to run performance-critical applications on multi-core processors is so-called "processor affinity" or "CPU pinning". This is an OS-specific feature that "binds" a running process or program to particular CPU core(s).

Binding a program to specific CPU cores can be beneficial in several scenarios. For example, when an application with highly cache-bound workload runs together with other CPU-intensive jobs, pinning the application to a specific CPU would reduce CPU cache misses. Also, when two processes communicate via shared memory intensively, scheduling both processes on the cores in the same NUMA domain would speed up their performance.

In this tutorial, I will describe how to run a program or process on specific CPU cores on Linux.


-------------------------------------------------分割线-----------------------------------------------------------------------------------------

google一圈,能够实现的方式有两种:第一种:linux的shell命令行方式,命令名字为taskset。第二种就是代码实现级别的了,pthread_setaffinity_np和sched_setaffinity函数接口。
         第一种方式我已经验证过了,确实可行。同时验证了我心中的疑问:如果将某个线程绑定到某个物理核上之后,在此线程运行结束前,会不会有别的线程被调度到此物理核上执行?  写了一个死循环验证了下,发现绑定之后是不会调度别的线程在此核上运行的!(肉眼观察的,时不时观察下,没发现别的线程在此核上执行;对比了下没有绑定的情况,会发现过段时间此线程就会被调度到别的核心上执行)
        此种方式有个问题,就是只有线程运行起来后才会被绑定到某个核上,不够及时。
        具体的方式为:
            1.首先根据系统的差别运行如下安装命令:
                  sudo apt-get install util-linux        (Debian,Ubuntu or Linux Mint)
                  sudo yum install util-linux             (Fedora,CentOS or RHEL)
            2.相关命令的使用:
                2.1 使用命令 taskset  -p  <PID> 来获得此Process的 CPU affinity。
                       eg: taskset -p 2915  ------> pid 2915's current affinity mask:ff; ff=="1111  1111",没一个1代表一个核,共8个核,能用的核数也为8个核。
                2.2 使用命令 taskset -cp  <PID> 可获得数字形式的CPU affinity。   
                       eg: taskset -cp 2915 ------> pid 2915's current affinity list: 0--7。
                接下来为将进程pin到某个核上的命令;
                2.3 taskset -p <COREMASK>  <PID>
                       eg:taskset -p 0x11 9030  ------> pid 9030's current affinity mask: ff , pid 9030's new affinity mask: 11 。意思就是将此进程绑定到了CPU core 0 and 4。
                2.4 taskset -cp <CORE-LIST>  <PID>   
                        eg:taskset -cp 0,4  9030  ------>the same as below.
                         With "-c" option, you can specify a list of numeric CPU core IDs separated by commas, or even include ranges (e.g., 0,2,5,6-10).
                2.5 taskset <COREMASK>  <EXECUTABLE>
                        eg: taskset 0x1 xxxx   ----->"xxxx" represented the name of one program.
另外:参考文章最后的位置说到,绑定到此物理核之后,别的进程(线程)还可以调度到此核上执行,但是没说绑定的这个线程没执行完之前是否会被别的线程挤掉。根据我的观察是不会被挤掉,这我在文章的开头也有提到。

第二种方式 还有待编码验证。
        “ 待实践后,再补充此部分

具体参考:http://xmodulo.com/run-program-process-specific-cpu-cores-linux.html 需要使用代理google之,要不然就被墙了,打不开。
也可以在linux下使用命令:man taskset。查看帮助。



### 新建线程后直接启动的行为及结果 在 Qt 中,创建并立即启动新线程通常会涉及 `QThread` 类及其成员函数 `start()`。当调用 `start()` 方法时,Qt 会在后台为该线程分配系统资源,并自动调用线程的 `run()` 方法[^4]。这意味着一旦线程被启动,它将进入运行状态并开始执行定义的任务。 需要注意的是,在默认情况下,任何在 `QThread` 子类中声明的对象都与其所属的线程绑定在一起。如果希望某些对象能够在其他线程运行,则应显式地使用 `moveToThread()` 将这些对象转移到目标线程中。 此外,直接调用 `QThread::run()` 而不是通过 `start()` 启动线程可能会导致未预期行为,因为这绕过了框架内部对线程生命周期管理的部分逻辑。 关于线程的安全终止也是不可忽视的一环。为了防止内存泄漏或其他潜在问题的发生,应当确保每一个开启的线程都能在其任务完成后正常退出;对于持续时间较长或者无限循环类型的线程来说尤其如此,它们可能需要额外机制来进行外部控制以便适时停止工作以防过度占用计算资源[^5]。 另外值得注意的一个方面就是跨平台兼容性和同步操作的重要性。虽然这里没有具体提及但实际开发当中不可避免遇到的就是如何正确处理多个并发进程间的数据共享与访问权限等问题——即所谓的互斥锁(mutexes) 和条件变量(condition variables),这些都是保障程序稳定性的关键技术点之一。 最后一点补充说明有关于 Python 或者 C++标准库中的实现差异对比的话, 可能还需要考虑到 joinable 属性的概念以及相应 API 设计上的区别对待方式等等细节之处[^2]. ```python class Worker(QObject): finished = pyqtSignal() def doWork(self): # Simulate some work. time.sleep(2) self.finished.emit() app = QCoreApplication([]) thread = QThread() worker = Worker() worker.moveToThread(thread) # Move worker to the new thread. # Connect signals and slots. thread.started.connect(worker.doWork) worker.finished.connect(thread.quit) worker.finished.connect(worker.deleteLater) thread.finished.connect(thread.deleteLater) # Start the thread. thread.start() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值