簡體   English   中英

Linux上的PThreads和MultiCore CPU

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM