PThreads и многоядерный процессор в Linux - PullRequest
13 голосов
/ 21 февраля 2011

Я пишу простое приложение, которое использует потоки для увеличения производительности. Проблема в том, что это приложение отлично работает на Windows, используя 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

Ответы [ 4 ]

19 голосов
/ 21 февраля 2011

clock () работает по-разному в Windows и Linux , поэтому не используйте это для измерения времени.В Linux он измеряет время процессора, в Windows - время настенных часов.В идеале это будет то же самое в этом тестовом примере, но вы должны использовать что-то непротиворечивое между платформами для измерения времени.Например, gettimeofday ()

rand () сериализует ваши потоки в linux. rand () содержит внутреннюю блокировку, чтобы обеспечить безопасность потоков.Состояния man-страницы rand () rand () не является поточно-ориентированным или реентерабельным, однако, по крайней мере, код в недавнем glibc фиксирует блокировку вызова.Я не уверен, как Windows справляется с этим, либо он вообще не безопасен для потоков, либо использует локальные переменные потоков.

Используйте rand_r в linux или найдите лучшую функцию загрузки ЦП для измерения.

void* function(void*)
{
    unsigned int seed = 42;
    int i=0;
    for(i=0; i<1110111; i++)
        rand_r(&seed);
    return 0;
}
8 голосов
/ 21 февраля 2011

Проблема в том, что многопоточная версия 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
0 голосов
/ 13 января 2015

Linux «видит» потоки как процессы, это означает, что все процессы являются потоками одного потока.

в таблице процессов (task_struct), когда мы создаем процесс, он создает PID, когда мы создаемвторой поток, тогда PID становится TGID (идентификатор группы потоков), и каждый поток получает TID (идентификатор потока).

В пользовательском пространстве мы увидим только первый поток (используя ps aux), но если мы выполним "ps-eLf "мы увидим новый столбец с именем LWP (облегченный процесс), который представляет собой TID.

, например, $ ps -eLfUID PID PPID LWP C NLWP STIME TTY TIME CMD

root 1356 1 1356 0 4 2014?00:00:00 / sbin / rsyslogdroot 1356 1 1357 0 4 2014?00:02:01 / sbin / rsyslogdroot 1356 1 1359 0 4 2014?00:01:55 / sbin / rsyslogdroot 1356 1 1360 0 4 2014?00:00:00 / sbin / rsyslogddbus 1377 1 1377 0 1 2014?00:00:00 dbus-daemon

Как мы видим, PID такой же, но реальный PID - это LWP (TID).Когда процесс имеет только один поток (например, демон dbus), PID = LWP (TID)

Внутренне ядро ​​всегда использует TID, такой как PID.

После этого ядро ​​сможетиспользовать расписание каждого потока, используя реальный параллелизм.

0 голосов
/ 21 февраля 2011

Для меня это звучит как реализация планировщика ОС.Сама по себе проблема в вашем коде.ОС решает, какой поток будет работать на каком ядре, и, если будут соблюдены правила соответствия потоков / процессоров, она будет каждый раз прикреплять этот поток к одному и тому же процессору.предмет.

...