参考资料:
http://blog.csdn.net/baodi_z/article/details/1857820
http://blog.csdn.net/cbnotes/article/details/38845069
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686223(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms683213(v=vs.85).aspx
简单说下步骤:
1、GetSystemInfo获取系统配置的处理器个数
2、用GetProcessAffinityMask和SetProcessAffinityMask确保当前进程可用系统配置的所有处理器
3、开启跟处理器个数相同的工作线程去做计算,为了充分利用CPU做计算,工作线程里面尽量不要存在有线程同步的代码(例如DEMO中的TRACE),除非有线程安全的需求必须这么做。
做了个简单的DEMO来测试
我的计算机用的处理器是 Intel i7 6700HQ,4核心的,经过测试,工作线程在达到4个的时候CPU就跑到100%了,3个工作线程只能跑到75%左右。最开始因为在计算循环里面放了TRACE,导致即便开了4个工作线程CPU也只能跑到50%,可见线程同步对CPU利用率的损耗有多大。
代码如下:
MyApp.h
1 #pragma once 2 3 #include <afxwin.h> 4 5 class CMyApp : 6 public CWinApp 7 { 8 public: 9 virtual BOOL InitInstance(); 10 };
MyApp.cpp
1 #include "MyApp.h" 2 3 4 5 using namespace std; 6 7 class CMainWindow : 8 public CFrameWnd 9 { 10 public: 11 CMainWindow(); 12 DECLARE_MESSAGE_MAP() 13 afx_msg void OnClose(); 14 }; 15 16 CMainWindow::CMainWindow() 17 { 18 Create(NULL, _T("The Hello Application"), WS_OVERLAPPED | WS_CAPTION | 19 WS_SYSMENU | WS_MINIMIZEBOX | WS_THICKFRAME, 20 CRect(32, 64, 352, 304)); 21 } 22 23 CMyApp myApp; 24 25 #define NUM_WORKER 4 // 工作线程个数 26 27 CWinThread* pWorker[NUM_WORKER]; // 工作线程 28 HANDLE hWorker[NUM_WORKER]; // 工作线程HANDLE 29 30 #define DATA_COUNT 20000 // 数据量 31 #define ROUNDS 4000 // 计算循环次数 32 33 // 耗时计算任务 34 UINT Task(LPVOID pParam) 35 { 36 double data[DATA_COUNT]; 37 double result = 1.0; 38 for (int i = 0; i < ROUNDS; ++i) 39 { 40 //TRACE(_T("[%d]Computing, Round[%d/%d] "), ::GetCurrentThreadId(), i, ROUNDS); // TRACE这个东西是线程安全的,线程同步问题导致CPU利用率上不去 41 for (int j = 0; j < DATA_COUNT; ++j) 42 data[j] = (double)(::rand()*(1.0 / RAND_MAX)); 43 for (int j = 0; j < DATA_COUNT; ++j) 44 { 45 data[j] = (double)::sin(::cos(data[j])); 46 result *= data[j]; 47 result /= data[j]; 48 } 49 } 50 TRACE(_T("[%d]Exiting "), ::GetCurrentThreadId()); 51 return 0; 52 } 53 54 // 主线程(UI) 55 BOOL CMyApp::InitInstance() 56 { 57 m_pMainWnd = new CMainWindow; 58 m_pMainWnd->ShowWindow(m_nCmdShow); 59 m_pMainWnd->UpdateWindow(); 60 61 SYSTEM_INFO SysInfo; 62 ::GetSystemInfo(&SysInfo); 63 64 TRACE(_T("处理器个数:%d "), SysInfo.dwNumberOfProcessors); 65 66 HANDLE hProcess = ::GetCurrentProcess(); // 本进程的HANDLE 67 DWORD dwSysMask, dwProcessMask; // 系统配置的所有处理器,本进程可用的处理器 68 69 ::GetProcessAffinityMask(hProcess, &dwProcessMask, &dwSysMask); // 获取 dwSysMask, dwProcessMask 70 71 if (dwProcessMask != dwSysMask) // 确保本进程可以使用系统配置的所有处理器 72 { 73 dwProcessMask = dwSysMask; 74 ::SetProcessAffinityMask(hProcess, dwProcessMask); 75 } 76 77 // 创建工作线程 78 for (int i = 0; i < NUM_WORKER; ++i) 79 { 80 CWinThread* pThread = ::AfxBeginThread(Task, NULL, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); 81 pThread->m_bAutoDelete = FALSE; 82 pWorker[i] = pThread; 83 hWorker[i] = pThread->m_hThread; 84 } 85 // 启动工作线程 86 for (int i = 0; i < NUM_WORKER; ++i) 87 { 88 pWorker[i]->ResumeThread(); 89 } 90 91 return TRUE; 92 } 93 94 BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd) 95 ON_WM_CLOSE() 96 END_MESSAGE_MAP() 97 98 // 退出主线程 99 void CMainWindow::OnClose() 100 { 101 102 ::WaitForMultipleObjects(NUM_WORKER, hWorker, TRUE, INFINITE); 103 104 for (int i = 0; i < NUM_WORKER; ++i) 105 { 106 delete pWorker[i]; 107 } 108 109 CFrameWnd::OnClose(); 110 }