[英]PThreads & MultiCore CPU on Linux
我正在編寫一個使用Threads來提高性能的簡單應用程序。 問題是,這個應用程序在Windows上運行正常,使用我的CPU擁有的2個內核。 但是當我在Linux上執行時,似乎只使用了1個Core。
我不明白為什么會這樣。
這些是我的代碼,C ++:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
void* function(void*)
{
int i=0;
for(i=0; i<1110111; i++)
rand();
return 0;
}
void withOutThreads(void)
{
function(0);
function(0);
}
void withThreads(void)
{
pthread_t* h1 = new pthread_t;
pthread_t* h2 = new pthread_t;
pthread_attr_t* atr = new pthread_attr_t;
pthread_attr_init(atr);
pthread_attr_setscope(atr,PTHREAD_SCOPE_SYSTEM);
pthread_create(h1,atr,function,0);
pthread_create(h2,atr,function,0);
pthread_join(*h1,0);
pthread_join(*h2,0);
pthread_attr_destroy(atr);
delete h1;
delete h2;
delete atr;
}
int main(void)
{
int ini,tim;
ini = clock();
withOutThreads();
tim = (int) ( 1000*(clock()-ini)/CLOCKS_PER_SEC );
printf("Time Sequential: %d ms\n",tim);
fflush(stdout);
ini = clock();
withThreads();
tim = (int) ( 1000*(clock()-ini)/CLOCKS_PER_SEC );
printf("Time Concurrent: %d ms\n",tim);
fflush(stdout);
return 0;
}
Linux上的輸出:
Time Sequential: 50 ms
Time Concurrent: 1610 ms
Windows上的輸出:
Time Sequential: 50 ms
Time Concurrent: 30 ms
clock()在windows vs linux上的工作方式不同 ,所以不要用它來測量時間。 在linux上它測量CPU時間,在Windows上它測量掛鍾時間。 理想情況下,在這個測試用例中這些是相同的,但是你應該使用平台之間的某些東西來測量時間。 例如gettimeofday()
rand()在linux上序列化你的線程。 rand()擁有一個內部鎖,以確保線程安全。 rand()管理頁面狀態rand()不是線程安全的,也不是可重入的,但至少最近的glibc中的代碼需要鎖定調用。 我不確定windows如何處理它,或者它根本不是線程安全的,或者它使用線程局部變量。
在linux上使用rand_r,或者找一些更好的CPU利用率來測量。
void* function(void*)
{
unsigned int seed = 42;
int i=0;
for(i=0; i<1110111; i++)
rand_r(&seed);
return 0;
}
問題是Linux多線程版本或rand()
鎖定互斥鎖。 將您的功能更改為:
void* function(void*)
{
int i=0;
unsigned rand_state = 0;
for(i=0; i<1110111; i++)
rand_r(&rand_state);
return 0;
}
輸出:
Time Sequential: 10 ms
Time Concurrent: 10 ms
Linux“看到”線程就像進程一樣,它意味着所有進程都是一個線程的線程。
在進程表(task_struct)中,當我們創建進程時,它創建了PID,當我們創建第二個線程時,PID成為TGID(線程組id),每個線程獲得一個TID(線程ID)。
在userland中,我們只會看到第一個線程(使用ps aux),但如果我們執行“ps -eLf”,我們將看到一個名為LWP(輕量級進程)的新列,即TID。
然后例如:$ ps -eLf
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1356 1 1356 0 4 2014? 00:00:00 / sbin / rsyslogd
root 1356 1 1357 0 4 2014? 00:02:01 / sbin / rsyslogd
root 1356 1 1359 0 4 2014? 00:01:55 / sbin / rsyslogd
root 1356 1 1360 0 4 2014? 00:00:00 / sbin / rsyslogd
dbus 1377 1 1377 0 1 2014? 00:00:00 dbus-daemon
我們可以看到PID是相同的,但真正的PID是LWP(TID)。 當進程只有一個線程(如dbus守護進程)時,PID = LWP(TID)
在內部,內核總是像PID那樣使用TID。
之后,內核將能夠使用實際並行性的每個線程使用調度。
這聽起來像是我的OS調度程序實現。 在您的代碼中本身不存在問題。 操作系統決定哪個線程將在哪個內核上運行,如果遵守線程/ CPU關聯性規則,它每次都會將該線程粘貼在同一個CPU上。
這是一個相當復雜的主題的簡單解釋。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.