Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Практическое применение многопоточности, Производительность при многопоточности 
:(
    Опции темы
SeriousMaksi
Дата 13.1.2011, 13:21 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 9.11.2008

Репутация: нет
Всего: нет



Здравствуйте!
Познакомился с книгой: http://forum.vingrad.ru/forum/topic-60076.html
и разработал программу для оценки производительности алгоритма при использовании нескольких потоков.
Тестирование проводилось на двухядерном процессоре.

Суть следующая: запускаются один, два потока (по выбору), принадлежащих одному классу, работа которых заключается в циклическом задании одной переменной случайного числа: "C:=random(256)". Причём потоки используют только внутренние переменные и не касаются основного потока и друг друга.

В результате, если время выполнения одного потока равна n секундам, то время выполнения двух потоков = ~n*4,7.
Причём тест с одним потоком загружает процессор на ~50%, а с двумя - 100%.

Собственно, напрашивается вопрос: почему время выполнения второго теста так сильно отличается, вместо, казалось бы, быть приблизительно равным с временем выполнения первого теста?

Это сообщение отредактировал(а) SeriousMaksi - 13.1.2011, 13:22
PM MAIL   Вверх
Snowy
Дата 13.1.2011, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



ну с процентами - это очевидно - при одном треде работает одно ядро, а при двух - 2 ядра.
Соответственно загрузка 1 ядра из двух на 100% - 50% загрузки двухъядерного процессора.
Или 25% загрузки 4-ядерного.

Что касается замеров - зависит от того, как они проводились, условия, параметры.
Возможно ты замеряешь время не только операции, но и создания и уничтожения тредов. 
Также длительность процесса. Создавать треды есть смысл только при длительных операциях.
Также может вмешиваться оптимизатор. И реально выполняется другой код, либо вообще ничего не выполняется.
Тут куча разных "если".
Так что на вопрос "почему", ответить в данной абстрактной ситуации маловероятно.
Можно только гадать.
PM MAIL   Вверх
SeriousMaksi
Дата 13.1.2011, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 9.11.2008

Репутация: нет
Всего: нет



Поменял функцию Random на число (из соображений, что Random() берёт данные у другого потока (timer)).

И так получил следующий простейший код потока:
Цитата

procedure RandomMAS.Execute;
var i,j:LongWord; C:byte;
begin 
  for i:=0 to 1000 do
  for j:=lowPar to hiPar do C:=76;
end;


Время выполнения второго теста в ~2,2 раза выше...
Как, всё-таки, подстроить этот пример чтобы было видно преимущество от использования многопоточности в многоядерном процессоре?
PS Здесь, видимо, проблема в плохо распределённом обращении к памяти, т.к. частота процессора выше частоты ОЗУ, то мне, похоже, нужен другой пример...
PM MAIL   Вверх
Frees
Дата 13.1.2011, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 9
Всего: 54



а код как время мерил покажи


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Snowy
Дата 13.1.2011, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



Твой код ничего не делает.
Даже с Random.
А уж тем более с обычным числом.
Оптимизатор просто выбрасывает твой код в мусор, как не имеющий смысла...
Ты меряешь пустоту.
А результат - погрешность.
PM MAIL   Вверх
SeriousMaksi
Дата 13.1.2011, 14:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 9.11.2008

Репутация: нет
Всего: нет



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

Код

...
{************************** КОД ОСНОВНОГО ПОТОКА (Button.Click())***************************}
numThread:=StrToInt(Edit1.text); partNum:=1000000 div numThread; // Получание числа потоков
for j:=1 to numThread do Begin // Создание, инициализация и запуск потоков
  NewThread[j]:=RandomMAS.Create(True);
  NewThread[j].FreeOnTerminate := True;
  NewThread[j].lowPar:=partNum*(j-1);
  NewThread[j].hiPar:=partNum*j-1;
  NewThread[j].PMAS:=@MAS;
  NewThread[j].gogo:=false; // Это датчик начала заполнения потоком своей части массива
  NewThread[j].OnTerminate:=OneThreadTerminate; // Ссылка на подпрограмму подсчёта затраченного времени
  NewThread[j].Resume; // Выполнить поток
End;

sleep(1000); // просто пауза для "разгона" потоков
OperationTime:=getTickCount(); // Замера времени
for j:=1 to numThread do NewThread[j].gogo:=true; // включить датчик начала заполнения

...

{****************************** ПОДСЧЁТ ВРЕМЕНИ *****************************}
procedure TForm1.OneThreadTerminate(Sender: TObject); // Подпрограмма подсчёта времени выполнения
begin
  Dec(numThread); // Счётчик завершённых потоков
  if (numThread=0) then showmessage(IntToStr(getTickCount()-OperationTime));
end;

...
{****************************** КОД ВНУТРЕННИХ ПОТОКОВ **********************}
procedure RandomMAS.Execute; // Исходный код потока
  var MAS:^TMAS; i,j:LongWord;
begin MAS:=PMAS;
  while NOT(gogo) do sleep(1); // Простой
  for i:=0 to 1000 do // Этот цикл для продолжительности вычислений
    for j:=lowPar to hiPar do MAS^[j]:=Random(High(Byte));
end;


Галиматья со свойством потока "gogo" понадобилась чтобы не учитывать како-либо время, затрачиваемое на создание, инициализацию, ... объекта класса потоков "RandomMAS".

Добавлено через 12 минут и 38 секунд
Цитата(Snowy @ 13.1.2011,  14:23)
Твой код ничего не делает.
Даже с Random.
А уж тем более с обычным числом.
Оптимизатор просто выбрасывает твой код в мусор, как не имеющий смысла...
Ты меряешь пустоту.
А результат - погрешность.

Если оставить код потока пустым (закомментировать оба цикла), то программа с любым числом потоков выдаст значение времени равное нулю! Т.е. стадии создания, выполнения, уничтожения даже пустого потока выполняются... Так что оптимизатор в данном случае и случае рассмотренном выше ничего не выкинул!
PM MAIL   Вверх
SeriousMaksi
Дата 14.1.2011, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 9.11.2008

Репутация: нет
Всего: нет



Господа, владеющие деликатным языком программирования, что-то вы туго пытаетесь разобраться в этой проблеме! Не разобравшись в распараллеливании алгоритмов вычисления, сегодня программирование теряет смысл...

Я продолжаю эксперименты и изменил процедуру потока следующим образом:
Код

procedure RandomMAS.Execute;
  var MAS:^TMAS; i,j:LongWord;
begin MAS:=PMAS;
  while NOT(gogo) do sleep(1); // Простой
  for i:=0 to 5000 do
    for j:=lowPar to hiPar do begin
     MAS^[j]:=j*2;
    end;
end;

... из соображений того, что функция Random - общая для всех потоков и её вызов последовательный, что и, возможно, сказывается на ожидании блокировок к одинаковым участкам памяти, занимаемой приложением...

С таким изменением, наконец-то, не зависимо от числа потоков время выполнения программы почти одинаково во всех тестах! Даже при числе потоков=10! Да, но процессор то двухядерный и где преимущество в случае его 100%'ой загрузки???

Объяснить отсутствие производительности многоядерников в этом случае можно последовательным доступом к ОЗУ и не сложной вычислительной операцией (j*2)...

Кто может, предложите какой-нибудь сложный алгоритм на место операции (j*2) с использованием сопроцессора и операций с плавающей запятой...
PM MAIL   Вверх
bems
Дата 15.1.2011, 22:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Цитата(SeriousMaksi @  14.1.2011,  10:43 Найти цитируемый пост)
Господа, владеющие деликатным языком программирования, что-то вы туго пытаетесь разобраться в этой проблеме! 
Уж не думает ли господин вопрошающий что ему кто-то что-то должен?



--------------------
Обижено школьников: 8
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0547 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.