【进程线程绑定CPU】总结
来源:互联网 发布:文件服务器java 编辑:程序博客网 时间:2024/05/18 00:03
本文整合了网上关于这块讲解比较详细的文章,转载者请注明!
本文参照1:http://topic.okbase.net/201010/2010101414/3909990.html
本文参照2:http://blog.csdn.net/zfive5/article/details/1499378
实现方法
进程与指定cpu绑定:SetProcessAffinityMask(GetCurrentProcess(), dwMask);
线程与指定cpu绑定:SetThreadAffinityMask(GetCurrentThread(),dwMask);
dwMask为CPU序号的或运算值:1(0001)代表只运行在CPU1,2(0010)代表只运行在CPU2,3(0011)代表可以运行在CPU1和CPU2,以此类推。
设置之前最好判断一下系统有几个CPU:
SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo);
CPU个数:SystemInfo.dwNumberOfProcessors
当前启用的CPU序号:SystemInfo.dwActiveProcessorMask,Mask representing the set of processors configured into the system. Bit 0 is processor 0; bit 31 is processor 31.
CPU亲缘性介绍
按照默认设置,当系统将线程分配给处理器时,Windows使用软亲缘性来进行操作。这意味着如果所有其他因素相同的话,它将设法在它上次运行的那个处理器上运行线程。让线程留在单个处理器上,有助于重复使用仍然在处理器的内存高速缓存中的数据。
有一种新的计算机结构,称为NUMA(非统一内存访问),在该结构中,计算机包含若干块插件板,每个插 件板上有4个CPU和它自己的内存区。当CPU访问的内存是它自己的插件板上的内存时,NUMA系统运行的性能最好。如果CPU需要访问位于另一个插件板上的内 存时,就会产生巨大的性能降低。在这样的环境中,就需要限制来自一个进程中的线程在共享同一个插件版的CPU上运行。为了适应这种计算机结构的需要,Windows允许你设置进程和线程的亲缘性。换句话说,你可以控制哪个CPU能够运行某些线程。这称为硬亲缘性。请注意,子进程可以继承进程的亲缘性。
注意:
(1)无论计算机中实际拥有多少个CPU,Windows98及以前系统只使用一个CPU,上述API不被支持。
(2)在大多数环境中,改变线程的亲缘性就会影响调度程序有效地在 各个CPU之间移植线程的能力,而这种能力可以最有效地使用CPU时间。应用场景举例:
将UI线程限制在一个CPU,将其他实时性要求较高的线程限制在另一个CPU。这样,当UI需要占用大量CPU时间时,就不会拖累其他实时性要求较高的线程的执行。同样可以将UI线程与一些优先级不高但耗时的异步运算线程设置在不同CPU上,避免UI给人卡顿的感觉。
附录:
SetThreadIdealProcessor(GetCurrentThread(),real_CPU_NUM);
SetThreadAffinityMask(GetCurrentThread(),real_CPU_NUM);
real_CPU_NUM为下面的DWORD值,在msdn上面查的
0x0001 1
0x0002 2
0x0003 1 or 2
0x0004 3
0x0005 1 or 3
0x0007 1, 2, or 3
0x000F 1, 2, 3, or 4
0x0001 00000000 00000001 1
0x0003 00000000 00000011 1 and 2
0x0007 00000000 00000111 1, 2 and 3
0x0009 00000000 00001001 1 and 4
0x007F 00000000 01111111 1, 2, 3, 4, 5, 6 and 7
实例1:
//get system info SYSTEM_INFO SystemInfo; GetSystemInfo(&SystemInfo); printf(" " "dwNumberOfProcessors=%u, dwActiveProcessorMask=%u, wProcessorLevel=%u, " "wProcessorArchitecture=%u, dwPageSize=%u ", SystemInfo.dwNumberOfProcessors, SystemInfo.dwActiveProcessorMask, SystemInfo.wProcessorLevel, SystemInfo.wProcessorArchitecture,SystemInfo.dwPageSize ); if(SystemInfo.dwNumberOfProcessors <= 1) return; DWORD dwMask = 0x0000; DWORD dwtmp = 0x0001; int nProcessorNum = 0; for(int i = 0; i < 32; i++) { if(SystemInfo.dwActiveProcessorMask & dwtmp) { nProcessorNum++; if(nProcessorNum <= 2) { //如果系统中有多个处理器,则选择第二个处理器 dwMask = dwtmp; } else { break; } } dwtmp *= 2; }//end of for //进程与指定cpu绑定 SetProcessAffinityMask(GetCurrentProcess(), dwMask); //线程与指定cpu绑定 //SetThreadAffinityMask(GetCurrentThread(),dwMask); return ;
实例2:
一个典型的应用:
将界面的线程限制在一个cpu,将其他实时性要求较高的线程限制在另一个cpu,这样,当界面需要占用大量cpu时间时,就不会拖累其他实时性要求较高的线程的执行。
前几天在客户现场调试设备时,客户的程序开了一个线程来兜各个状态,并显示各个动作所花费的时间,用鼠标拖拽界面进行移动时,CPU资源耗费很高,设备运 行的速度也随之下降。为了解决这个问题,我们想办法将线程绑定到另一颗CPU上,实现方法如下。
首先用API函数创建一个线程,
HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // SDSIZE_T dwStackSize, // initial stack sizeLPTHREAD_START_ROUTINE lpStartAddress, // thread functionLPVOID lpParameter, // thread argumentDWORD dwCreationFlags, // creation optionLPDWORD lpThreadId // thread identifier);//通过调用SetThreadAffinityMask,就能为各个线程设置亲缘性屏蔽: DWORD_PTR SetThreadAffinityMask(HANDLE hThread, DWORD_PTR dwThreadAffinityMask); //该函数中的h T h r e a d参数用于指明要限制哪个线程, dwThreadAffinityMask用于指明该线程能够在哪个CPU上运行。dwThreadAffinityMask必须是进程的亲缘性屏蔽的///相应子集。返回值是线程的前一个亲缘性屏蔽。因此,若要将3个线程限制到CPU1、2和3上去运行,可以这样操作: //Thread 0 can only run on CPU 0. SetThreadAffinityMask(hThread0, 0x00000001); //Threads 1, 2, 3 run on CPUs 1. SetThreadAffinityMask(hThread1, 0x0000000E);经试验,此方法解决了客户拖拽界面导致整台设备变慢的问题。
实例3:
多cpu下SetThreadAffinityMask运用框架
Author:zfive5(zidong)
Email :zfive5@yahoo.com.cn
“舍”的目的,是为了“得”!
随着多cpu机器的普及时代的到来,大家对机器速度的提升感到欣喜若狂的同时,对cpu的掌控能力越来越差了,也许大家对这块也不是特别注意或感兴趣,但如果真等到需要这方面的答案时,又会无言,例如:
mov eax,1
这条指令在core2的机器上想在cpu1(这里为了区别另一个cpu而给它取的名称罢了)上执行?而不是让操作系统根据它的调度算法去选择1或2,估计大家只能保持沉没!感慨大家现在都让操作系统包装成了高科技的傻子,本着不想让操作系统玩弄鼓掌的态度,我在msdn游荡了数小时,为的是一个api的出现,终于SetThreadAffinityMask出现了,说真的此时的心情就像佛教徒们看到了佛祖猞猁那样!关于SetThreadAffinityMask这个函数的介绍大家可以到msdn去搜!
下面写一个SetThreadAffinityMask框架,大家去以后需要套用即可!
static DWORD WINAPI ZFive5Proc(LPVOID p){ //自己需要控制代码开始 _asm{ push eax mov eax,1 pop eax } sprintf((char*)p,"zfive5! good"); //自己需要控制代码结束 return 0;}void CCPUDlg::OnOK() { // TODO: Add extra validation here //CDialog::OnOK(); char szbuf[200]; DWORD id; HANDLE hHandle=CreateThread(NULL,0,ZFive5Proc,&szbuf,CREATE_SUSPENDED ,&id); if(hHandle==NULL) { AfxMessageBox("zfive5! error"); return; } //CPU1 SetThreadAffinityMask(hHandle,1); //CPU2 //SetThreadAffinityMask(hHandle,2); ResumeThread(hHandle); if(WaitForSingleObject(hHandle,INFINITE)!=WAIT_OBJECT_0) { AfxMessageBox("zfive5! error"); CloseHandle(hHandle); return; } CloseHandle(hHandle); //TRACE("%s/r/n",szbuf); AfxMessageBox(szbuf); return;}
这样就可以让线程的代码ZFive5Proc在cpu1上执行了!
写到这里想起了我中熊猫烧香的经历,就是鼠标点了一下跟目录的图标(windows隐藏了autorun.inf运行)!
昨天看kaspersky,发现它的界面是通过贴窗体来实现的!今天在同事的机器上看到macfee,发现界面很一般!
- 【进程线程绑定CPU】总结
- 进程线程与cpu绑定
- 【历程线程绑定CPU】总结
- Linux下CPU绑定线程、进程
- Visual C++学习总结——进程或线程与指定CPU绑定
- X86下进程克隆及与CPU线程绑定介绍
- windows下绑定线程(进程)到指定CPU
- 查看进程绑定cpu
- 绑定进程与CPU
- 线程绑定CPU核
- 线程cpu绑定技术
- 线程绑定CPU
- 为线程绑定CPU
- 线程绑定CPU核
- 线程绑定CPU核
- 线程绑定CPU核
- 线程绑定CPU核
- 线程绑定CPU核
- 多元正态分布
- 约瑟夫环 - 循环链表
- atof,atol,atrtod,strtol,strtoul的使用
- ACM--多重继承
- javascript怎么刷新当前页面
- 【进程线程绑定CPU】总结
- JAVA年度安全 第八周 HTTP严格传输安全协议
- 简单的windows运行命令
- 还原sql server 数据库(.bak文件)
- java.lang.OutOfMemoryError: Java heap space 解决方法
- ipad上如何进行页面调试
- 第一次写博客的感受
- AMD 和 CMD 的区别有哪些
- com.sun.jersey.multipart.impl.MultiPartReaderClientSide.unquoteMediaTypeParameters