2014-01-25 3 views
0

Я сделал небольшую программу, чтобы наблюдать за ускорением использования двух потоков. Я задаю время для заполнения массива. A основной поток и call1 call function_1 для инициализации разных половин массива. Я ожидал увидеть более быстрые результаты, используя два потока. Вместо этого у меня есть более медленные времена, и код с комментариями работает быстрее. Где я ошибаюсь?Производительность нити C++

#include <chrono> 
#include <iostream> 
#include <vector> 
#include <thread> 


void function_1(int I, int J, int *B){ 
    for (int i = I; i<(J+1); i++) { 
     B[i] = 100; 
     //std::cout << B[i] << std::endl; 
    } 
} 

int *count; 

int main(int argc, const char * argv[]) 
{ 
    count = new int[20000]; 

    std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now(); 
    //function_1(0, 19999, count); 
    std::thread thread1(function_1, 0, 9999, count); 
    thread1.join(); 
    function_1(10000, 19999, count); 

    std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now(); 
    auto time_span = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count(); 
    std::cout << "time taken is :" <<time_span << " ms"<<std::endl; 

    return 0; 
} 

ответ

2

Вы выполняете свой пример кода синхронно, сразу же присоединив thread1 сразу после его создания. Выполнение в main() будет блокироваться до тех пор, пока этот поток не завершит обработку, а затем переместится на function_1(10000, 19999, count);. Чтобы воспользоваться дополнительным потоком, попробуйте переместить вызов соединения после вызова в function_1(10000, 19999, count);.

+0

Я переместил thread1.join() после вызова main в функцию_1. По какой-то причине использование двух потоков еще медленнее, чем использование одного потока с кодом с комментариями. – gumby

+1

Тест кажется слишком тривиальным. Управление потоками, скорее всего, влияет на вашу производительность отрицательно. Нитки - это не беспроигрышный способ параллельной работы. –

+1

@Mario: Это действительно небольшое количество работы. Вы можете попробовать сделать массив в 10 или 100 раз больше. – Blastfurnace

2
std::thread thread1(function_1, 0, 9999, count); 
thread1.join(); 
function_1(10000, 19999, count); 

Основной поток будет ждать thread1, чтобы завершить работу перед вызовом function_1. Это то же самое, что и позвонить

function_1(...) 
function_1(...) 

в основной теме, только с учетом дополнительных затрат, связанных с управлением потоками. Вы можете захотеть join() после того, как вы позвоните function_1 в основной поток.

Кроме того, вы должны увеличить рабочую нагрузку, чтобы сделать тестирование более актуальным. Нитки - это не бесплатный способ быстро выполнить работу. Вы должны учитывать затраты на поддержание потоков, прежде чем принимать решение о том, имеют ли они отношение к вашей ситуации.

+0

Я переместил вызов основного потока функции_1 под созданием thread1 и перед thread1.join(). Временные результаты немного улучшены по сравнению с исходными результатами. Но по какой-то причине это происходит не быстрее, чем использование одного потока с кодом с комментариями. – gumby

+0

См. Комментарии к другому ответу или моему правлению. –

0

Вы вряд ли увидите значительное улучшение, когда задача состоит только в заполнении памяти.

Проблема довольно проста: одно ядро ​​может, вероятно, насытить вашу полную пропускную способность до памяти. В этом случае добавление большего количества потоков не может принести много пользы, если у вас нет компьютера с несколькими процессорами, а не только нескольких ядер в одном сокете.

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

Ни одна из них не является точно наукой о ракете, но они также не обязательно тривиальны. Даже в самом простом, по крайней мере, немного кода почти наверняка не переносится.

Чтобы увидеть большой выигрыш в нескольких потоках, вы обычно выполняете задачи, которые включают в себя смесь различных видов работы: например, некоторые из них связаны с вводом-выводом, некоторые связаны с памятью, а некоторые связаны с процессором , В таком случае намного легче получить значительное ускорение от нескольких потоков. Если вы не можете этого сделать, то, что сильно связано с процессором, вероятно, является вторым выбором. Предполагая, что вы можете сделать это с небольшой или не синхронизацией потоков, вероятность того, что вы можете получить примерно линейное ускорение (т. Е. N ядер выполняют код примерно в N раз быстрее, чем одно ядро).

Смежные вопросы