2008-08-05 21 views
37

我只是想知道是否有一種優雅的方式來設置特定線程進行密集計算的最大CPU負載。


現在我已經找到線程中最耗時的循環(它只能進行壓縮),並使用帶硬編碼值的GetTickCount()Sleep()。它確保循環持續一段時間,並且在一定的最短時間內睡眠。它或多或少地確保線程不會佔用超過50%的CPU。
但是,行爲取決於CPU內核的數量(巨大的缺點)並且簡單醜陋(更小的缺點:))。
有什麼想法?在C++中CPU節流

+1

你想實現什麼樣的可見行爲?也就是說,這個監督人員想要從你的線索中得到什麼?他們絕不應該使用超過80%的CPU嗎?可以將進程基地優先級設置爲閒置可能使WD平靜嗎? – wordmonger 2008-08-11 19:52:53

回答

17

我不知道有任何API可以讓操作系統的調度程序做你想做的事情(即使你的線程空閒優先級,如果沒有更高優先級的就緒線程,你將運行)。不過,我認爲你可以根據你已經在做的事情來製作一個相當優雅的節流功能。基本上(我沒有一個Windows開發機器,方便):

選擇一個線程每次迭代將默認的睡眠時間。然後,在每個迭代(或每n次迭代,從而使流量調節功能本身並不成爲一個顯著的CPU負載),

  1. 計算自從上次你節流功能使用您的線程的CPU時間量被稱爲(我會稱之爲dCPU)。您可以使用GetThreadTimes() API來獲取線程執行的時間。
  2. 計算自上次調用throttling函數以來流逝的實時量(我將調用此dClock)。
  3. dCPU/dClock是CPU使用率(一個CPU)的百分比。如果它高於你想要的,增加你的睡眠時間,如果降低,減少睡眠時間。
  4. 讓您的線程在計算時間內休眠。

根據您的看門狗如何計算CPU使用率,您可能需要使用GetProcessAffinityMask()來查明系統有多少個CPU。 dCPU /(dClock * CPU)是可用CPU總時間的百分比。

對於初始睡眠時間和增加/減少量,您仍然需要選擇一些神奇數字,但我認爲可以調整此算法以使線程保持相當接近CPU的確定百分比。

+0

如果你的目標是爲了避免浪費CPU時間,更便宜的啓發式可能是更好的選擇。根據您的線程在高系統負載下自行捱餓的問題的多少,您可以*檢查經過的掛鐘時間。在x86上,這很便宜,因爲基於`rdtsc`的時間函數甚至不需要進入內核模式。進行多次系統調用甚至是「n」次迭代都比只做一次更糟糕,除非它可以讓你大量增加`n`並且仍然可以得到你想要的行爲。 – 2016-05-11 07:57:39

2

我想不出你想要什麼任何跨平臺的方式(或者任何保證方式完全停止),但由於您使用的GetTickCount也許你不感興趣的跨平臺:)

我會使用進程間通信並將密集的進程設置爲很好的級別以獲得您所需的內容,但我不確定這適合您的情況。

編輯: 我同意Bernard這就是爲什麼我認爲一個過程而不是一個線程可能更合適,但它可能不符合您的目的。

4

在linux上,您可以使用nice()更改線程的調度優先級。

+0

其他平臺也有類似的功能,請參閱:https://stackoverflow.com/questions/18884510/portable-way-of-setting-stdthread-priority-in-c11我認爲這可以是一個很好的解決方案,儘管不同的語義 - 即沒有50%的CPU消耗保證 – milianw 2018-01-08 09:03:16

2

問題是,當你有工作要離開CPU空閒時,這是不正常的。通常情況下,您將後臺任務設置爲IDLE優先級,並讓操作系統處理交互式任務未使用的所有CPU時間。

這聽起來像問題是看門狗過程。

如果您的後臺任務受到CPU限制,那麼您希望它爲其任務執行所有未使用的CPU時間。

也許你應該看看修復看門狗程序?

+1

想要一個空閒的CPU是非常合理的。也許你想做一些計算,但不關心它完成的速度有多快,只要它不會使筆記本電腦上的CPU風扇旋轉起來。 – Ringding 2009-09-21 10:32:35

0

您可能能夠更改線程的優先級,但更改最大利用率要麼需要輪詢和黑客來限制正在發生的事情,要麼使用可設置進程的最大利用率的操作系統工具。 但是,我沒有看到你想要這樣做的任何情況。