Нужны мысли о профилировании многопоточности в C в Linux

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

i) 1-процесс: программа без какой-либо потоковой передачи и обрабатывает данные от 1M .. 1G, в то время как система предполагала запуск только одного ядра из своих 4-ядер.

ii) 4-поточный процесс: программа с 4-мя потоками (все потоки выполняют одну и ту же операцию), но обрабатывают 25% входных данных.

В моей программе для создания 4 потоков я использовал параметры pthread по умолчанию (т.е. без какого-либо конкретного pthread_attr_t). Я считаю, что прирост производительности конфигурации с четырьмя потоками по сравнению с конфигурацией с одним процессом должен быть ближе к 400% (или где-то между 350% и 400%).

Я профилировал время, потраченное на создание потоков, как показано ниже:

timer_start(&threadCreationTimer); 
pthread_create( &thread0, NULL, fun0, NULL );
pthread_create( &thread1, NULL, fun1, NULL );
pthread_create( &thread2, NULL, fun2, NULL );
pthread_create( &thread3, NULL, fun3, NULL );
threadCreationTime = timer_stop(&threadCreationTimer);

pthread_join(&thread0, NULL);
pthread_join(&thread1, NULL);
pthread_join(&thread2, NULL);
pthread_join(&thread3, NULL);    

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

timer_start(&threadTimer[i]);
while(!dataFinished[i])
{
    threadTime[i] += timer_stop(&threadTimer[i]);
    data_source();
    timer_start(&threadTimer[i]);
    process();
}
threadTime[i] += timer_stop(&threadTimer[i]);

Переменная dataFinished [i] помечена true процессом, когда он получил и обработал все необходимые данные . Process () знает, когда это делать: -)

В основной функции я вычисляю время, затрачиваемое на 4-поточную конфигурацию, как показано ниже:

execTime4Thread = max (threadTime [0] , threadTime [1], threadTime [2], threadTime [3]) + threadCreationTime .

Прирост производительности вычисляется просто по формуле

gain = execTime1process / execTime4Thread * 100

Проблема: При небольшом размере данных от 1 до 4 МБ прирост производительности обычно хороший (от 350% до 400%). Однако тенденция увеличения производительности экспоненциально уменьшается с увеличением размера входных данных. Он продолжает уменьшаться до тех пор, пока некоторый размер данных не достигнет 50 МБ или около того, а затем станет стабильным около 200%. Достигнув этой точки, он остается почти стабильным даже для 1 ГБ данных.

Мой вопрос: может ли кто-нибудь предложить основную причину такого поведения (т.е., производительность падает вначале, но остается стабильной позже)?

И предложения, как это исправить?

Для вашей информации, я также исследовал поведение threadCreationTime и threadTime для каждого потока, чтобы увидеть, что происходит. Для 1M данных значения этих переменных малы, но с увеличением размера данных обе эти две переменные увеличиваются экспоненциально (но threadCreationTime должно оставаться почти таким же, независимо от размера данных и threadTime должен увеличиваться со скоростью, соответствующей обрабатываемым данным). После продолжения увеличения примерно до 50 МБ threadCreationTime становится стабильным, а threadTime (точно так же, как падение производительности становится стабильным) и threadCreationTime продолжают увеличиваться с постоянной скоростью, соответствующей увеличению в обрабатываемых данных (что считается понятным).

Как вы думаете, может ли помочь увеличение размера стека каждого потока, приоритета процесса или пользовательских значений другого типа параметров планировщика (с использованием pthread_attr_init )?

PS: Результаты получаются во время работы программы под Linux в отказоустойчивом режиме с root (т.е. минимальная ОС работает без графического интерфейса и сетевого оборудования).

7
задан Junaid 14 December 2011 в 11:30
поделиться