Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Оптимизация многопоточного приложения  (Прочитано 18624 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
Kultura
Помогающий

ru
Offline Offline

« : 27-03-2009 09:37 » 

Изучаю потоки на примере простенькой игрушки - пакмене. Возникли проблемы со скоростью приложения: процессор загружается на ~100% и сама игрушка тормозит  Да можно...

Есть 5 разных существ (пакмен и враги), для каждого запускается по отдельному потоку. В каждом потоке - бесконечный цикл, в котором несколько проверок плюс изменение координаты, а для врагов еще поиск пути (пока что почти пустой). После изменения координаты - Sleep (creatureSpeed).
С одним таким потоком (один пакмен бегает по карте) загрузка процессора - 30-40%. А с 5-ю еще вдобавок скорость перемещения существ падает (видимо к Sleep-у добавляется не такое уж и маленькое время расчетов)

В общем, вопрос: как сделать правильно?

Записан
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 27-03-2009 09:41 » 

Kultura, если нужно делать движения с некоторой частотой - то для такого есть таймеры. И если sleep слишком маленький - определённо, будут проблемы с загрузкой.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 27-03-2009 10:01 » 

Kultura, лучше такой подход: поток, исполняемый по таймеру; после появления события таймер останавить; обработка объектов выполняется последовательно; перерисовать картинку; в конце цикла таймер запустить.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
sss
Специалист

ru
Offline Offline

« Ответ #3 : 27-03-2009 10:11 » 

Kultura, ты теряешь всю производительность на переключение контекстов потоков. Бесполезно оптимизировать... Технически, все технологии отходят от параллельных интерфейсов к последовательным. Получается быстрее и проще.
Записан

while (8==8)
Kultura
Помогающий

ru
Offline Offline

« Ответ #4 : 27-03-2009 10:26 » 

RXL, т.е., например, таймер изменяет какой-нибудь флаг, а в потоке бесконечным циклом этот флаг опрашивается. Когда флаг активный - выполняется обработка объектов, таймер перезапускается? Это как я понял, или речь идет о чем-то другом?

Вад, sss, все таки надо сделать именно с потоками (в обучающих целях). Но, получается, многопоточность только проигрывает на одноядерных процессорах?
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #5 : 27-03-2009 10:48 » 

просто вы не умеет их готовить.

я пока из причин для подобного поведения вижу только:
1. маленький слип
2. не очень удачная реализация отрисовки.

и профайлером пройдись по коду.
или самописным или нормальным Улыбаюсь VTune скачай триальный месяцок погонять.
Записан

Странно всё это....
Kultura
Помогающий

ru
Offline Offline

« Ответ #6 : 27-03-2009 11:07 » 

LogRus, Sleep (10), проверка проходимости, перемещение на 1 пиксель, обновление экрана, Sleep (10)...
Записан
Kultura
Помогающий

ru
Offline Offline

« Ответ #7 : 27-03-2009 11:14 » 

Цитата
2. не очень удачная реализация отрисовки.
Закомментил отрисовку карты (поле 20 на 20, например, простые прямоугольники), тормоза ушли. Каждый из 5-ти потоков перерисовывал всю карту  Скромно так...
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #8 : 27-03-2009 15:04 » 

Улыбаюсь я бы завёл один поток для отрисовки

а вы говорите переключение контекста.
Записан

Странно всё это....
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 28-03-2009 16:28 » new

RXL, т.е., например, таймер изменяет какой-нибудь флаг, а в потоке бесконечным циклом этот флаг опрашивается. Когда флаг активный - выполняется обработка объектов, таймер перезапускается? Это как я понял, или речь идет о чем-то другом?

Вад, sss, все таки надо сделать именно с потоками (в обучающих целях). Но, получается, многопоточность только проигрывает на одноядерных процессорах?

Забудь о бесконечных циклах ожидания - это бесполезная трата процессорного времени.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
sss
Специалист

ru
Offline Offline

« Ответ #10 : 30-03-2009 01:33 » 

Вад, sss, все таки надо сделать именно с потоками (в обучающих целях). Но, получается, многопоточность только проигрывает на одноядерных процессорах?

Проигрывает кому? Пакману в однопоточном DOS варианте на таком же процессоре? Конечно... Только программировать сложнее.
Записан

while (8==8)
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #11 : 30-03-2009 03:50 » 

Забудь о бесконечных циклах ожидания - это бесполезная трата процессорного времени.

а если поток спит в этом цикле в ожидании события?
Записан

Странно всё это....
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #12 : 30-03-2009 09:30 » 

Kultura, главная игровая петля - это в том или ином виде (99% всех игр):
Код:
while (1)
{
    Indut();  // получение данных с клавиатуры, миши и т.п.
    Update(); // ИИ, передвижение объектов и т.п.
    Draw();   // Формирование картинки и вывод ее на экран
}
И я думаю Ты прекрасно понимаешь, что начинать рисовать картинку прежде чем будет завершено передвижение всех объектов не имеет смысла.

Если ты двигаешь объекты [Update()] в отдельном потоке, то должен каким то способом проинформировать основной, что все передвижения завершены и можно рисовать картинку [Draw()].

А тот способ который используешь Ты, каждый поток рассчитывает положение своего объекта и потом сам же его рисует это самое плохое что можно придумать.

P.S. 80% всего времени работы программы занимает перенос картинки на экран.
Записан
Kultura
Помогающий

ru
Offline Offline

« Ответ #13 : 01-04-2009 09:49 » 

Serg79, это очень интересная тема - структура игровых приложений. Хотел бы узнать подробнее.
На геймдеве про это ничего нет, есть только отдельные эллементы. Слышал, даже есть специальные игровые паттерны. Где бы почитать?

Только недавно узнал, что используются бесконечные циклы и то случайно.

У меня сразу 2 вопроса.
По Input (): если в этой фунции мы опрашиваем состояние клавиш, а во время Sleep () была нажата кнопка - ее мы пропускаем (а может быть, наоборот во время нажатия цикл несколько раз прокрутится)?
По Draw (): если в игре серьезная графика (я пока что о 2д и gui), слишком часто обновлять все не получится. Но персонажи движутся и окружение около них должно обновляться. Как эта проблема решается?
« Последнее редактирование: 01-04-2009 11:58 от Kultura » Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 01-04-2009 17:00 » 

По Input (): если в этой фунции мы опрашиваем состояние клавиш, а во время Sleep () была нажата кнопка - ее мы пропускаем (а может быть, наоборот во время нажатия цикл несколько раз прокрутится)?
Обычно за секунду кнопки и мышь опрашивается ~30 раз, я не думаю, что Ты способен барабанить по кнопкам с частотой превышающей 30 Гц. Улыбаюсь

По Draw (): если в игре серьезная графика (я пока что о 2д и gui), слишком часто обновлять все не получится. Но персонажи движутся и окружение около них должно обновляться. Как эта проблема решается?
Слишком часто обновлять картинку то же не надо. Вполне комфортно для глаз будет если Ты картинку будешь обновлять 30 раз в секунду, 33 ms. для построения картинки более чем достаточно да же на PII.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #15 : 23-12-2009 19:24 » 

Kultura,
По Input размер sleep вообще никакого отношения к моменту нажатия клавиши не имеет (ну почти, если таймаут не гигантский).
По Draw:
1. в наше время (на самом средненьком/простеньком компе) никаких проблем с "очень частым" обновлением нет
2. игр пишутся так, что никакой задержки (sleep) в них нет или почти нет, т.е. она минимальна (кто как), просто fps будет больше. Более того точность sleep примерно 50 мс, поэтому аргумент менее 50 ставить в sleep бесполезно (есть гораздо более точные таймеры)
 Serg79,
на самом деле, делать так
while (1)
{
    Indut();  // получение данных с клавиатуры, миши и т.п.
    Update(); // ИИ, передвижение объектов и т.п.
    Draw();   // Формирование картинки и вывод ее на экран
}
достаточно прогрессивно (не совсем так, но смысл именно в том, что отрисовка приходится на каждый "тик"), именно так разрабатываются современные серьезные системы реального времени (игрушки типичный представитель), дело в том, что для игры, как и для любой программы приоритеным является логика, а не отображение. В случае, когда расчет мира занимает много времени (ну такой момент, когда все во всех стреляют и т.д.) при последовательном отображении на экран картинки фпс будет катострофически мал (отрисовка само по себе очень не быстрая операция) и скорость обсчета мира просто ляжет. Поэтому отрисовка, в такие "сложные моменты", иногда пропускается (ничего страшного если мы будем отображать не каждый кадр а через кадр и т.д.).
Пропуск может осуществляться разными способами (как последовательной обработкой мира и отрисовки, так и параллельной)
« Последнее редактирование: 23-12-2009 19:27 от lapulya » Записан

С уважением Lapulya
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines