2012-11-23 65 views
1

我正在寫一個使用一定比例的CPU的小程序。基本策略是,我將持續檢查CPU使用情況,並在使用級別高於給定值時使進程處於睡眠狀態。另外,由於我使用的是MacOS(沒有像Linux一樣的proc/stat,C#中沒有PerformanceCounter),所以我必須在另一個線程中執行top命令並從中獲得CPU使用率。多線程C程序中的共享字段是否使用CPU很多?

問題是我一直在獲得CPU的非常高的使用率,即使我給出一個小的值作爲參數。經過多次實驗,似乎是由多線程共享字段造成的。

這裏是我的代碼(代碼1)和實驗:

(代碼2)起初,我還以爲它是shell命令使使用率非常高,所以我在run()評論的無限循環,只留下getCpuUsage()運行。但是,CPU使用率幾乎爲零。

(代碼3)然後,我編寫了另一個run()獨立於cpuUsage的函數,該函數旨在使用50%的CPU。它運作良好!我認爲代碼1和代碼3的唯一區別是cpuUsage的使用。所以我想知道如果在線程之間共享字段會使用很多CPU?

代碼1

const char CPU_COMMAND[] = "top -stats cpu -l 1 -n 0| grep CPU\\ usage | cut -c 12-15"; 

int cpuUsage; // shared field that stores the cpu usage 

// thread that continuously check CPU usage 
// and store it in cpuUsage 
void getCpuUsage() { 
    char usage[3]; 
    FILE *out; 
    while (1) { 
     out = popen(CPU_COMMAND, "r"); 
     if (fgets(usage, 3, out) != NULL) { 
      cpuUsage = atof(usage); 
     } else { 
      cpuUsage = 0; 
     } 
     pclose(out); 
    } 
} 

// keep the CPU usage under ratio 
void run(int ratio) { 
    pthread_t id; 
    int ret = pthread_create(&id, NULL, (void *)getCpuUsage, NULL); 
    if (ret!=0) printf("thread error!"); 

    while (1) { 
     // if current cpu usage is higher than ration, make it asleep 
     if (cpuUsage > ratio) { 
      usleep(10); 
     } 
    } 

    pthread_join(id, NULL); 
} 

代碼2

// keep the CPU usage under ratio 
void run(int ratio) { 
    pthread_t id; 
    int ret = pthread_create(&id, NULL, (void *)getCpuUsage, NULL); 
    if (ret!=0) printf("thread error!"); 

    /*while (1) { 
     // if current cpu usage is higher than ration, make it asleep 
     if (cpuUsage > ratio) { 
      usleep(10); 
     } 
    }*/ 

    pthread_join(id, NULL); 
} 

代碼3

void run() { 
    const clock_t busyTime = 10; 
    const clock_t idleTime = busyTime; 

    while (1) { 
     clock_t startTime = clock(); 
     while (clock() - startTime <= busyTime); 
     usleep(idleTime); 
    } 
} 
+0

sleep不會停止線程的CPU使用率。 –

+0

@MarrowGnower,但是我的代碼的第三個版本效果很好,這表明'usleep()'確實會停止CPU使用。 – POPOL

+0

順便說一句,POSIX不允許通過多個控制線程同時讀取和寫入存儲器位置 - 「應用程序應確保受到多於一個控制線程(線程或進程)對任何存儲器位置的訪問受到限制,使得沒有線程的控制可以讀取或修改內存位置,而另一個控制線程可能正在修改它。「 – chill

回答

2

多線程C程序中的共享字段是否使用CPU很多?

是的,通過多個CPU上的多個線程對共享內存位置進行持續讀/寫操作會導致緩存行在CPU之間不斷移動(緩存反彈)。國際海事組織稱,這是導致幼稚的「並行」應用程序可擴展性差的唯一最重要的原因。

1

好的。 Code1創建一個線程 - 儘可能快 - 做一個popen。所以這個線程耗盡了所有的CPU時間。另一個線程(主線程)確實休眠,但不是線程...

Code2也啓動這個cpu-using線程,然後等待它完成(連接),這將永遠不會發生。

Code3運行一段時間,然後睡覺相同的數量,所以它應該用完了大約50%。所以基本上你應該做什麼(如果你真的想用top來達到這個目的的話),你可以調用它,然後讓它睡1秒或100ms,然後看看代碼1中的主循環是否調整過。

while (1) { 
    usleep (100*1000); 
    out = popen(CPU_COMMAND, "r"); 
+0

'runUsage()'函數在run()變化時保持不變。所以代碼2可以證明'getUsage()'沒有使用太多的CPU時間。 – POPOL