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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Многопоточное программирование, несколько вопросов 
:(
    Опции темы
ilyalyu
Дата 1.4.2007, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Эти вопросы относятся по-видимому не конкретно к c++, а к многопоточному программированию в целом.

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

| Начало стека (занято)
| Место под локальные переменные потока 1
| Место под локальные переменные потока 2
| Конец стека (свободно)

Если так, то правильно ли, что выход из функции, вызванной внутри потока 1, сможет произойти только после завершения функции, вызванной внутри потока 2? В противном случае получится следующее:

| Начало стека (занято)
| Середина стека (свободно - !!!)
| Место под локальные переменные потока 2
| Конец стека (свободно)

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

2. Я использую в программе критические секции. Для того чтобы исключить недопонимание, отмечу, что число критических секций НЕ ЕСТЬ число входов/выходов из критической секции (т.е. критическая секция может быть одна, а число входов/выходов много). Так вот вопрос в следующем. (1) Насколько критичным для скорости выполнения программы является использование большого количества критических секций (допустим порядка 1000). (2) Тот же вопрос, но уже относительно входов/выходов из критическую секцию. Например, насколько замедлится программа, если входы/выходы будут происходить через каждые 10 строчек (при этом считаем, что медленных операций, типа чтения/записи в файл, там нет).
PM MAIL   Вверх
Daevaorn
Дата 1.4.2007, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

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



у каждого потока свой стек
PM MAIL WWW   Вверх
ilyalyu
Дата 1.4.2007, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Daevaorn @ 1.4.2007,  14:27)
у каждого потока свой стек

Ясно. С первым вопросом разобрались. Спасибо!!!

Кстати, забыл спросить. А насколько эффективно использование большого количества потоков. Например, порядка тысячи. Например, не окжется ли, что переключение между потоками будет занимать 90% процессорного времени и т.д.

Это сообщение отредактировал(а) ilyalyu - 1.4.2007, 14:42
PM MAIL   Вверх
dumb
Дата 1.4.2007, 17:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

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



Цитата(ilyalyu @  1.4.2007,  14:42 Найти цитируемый пост)
А насколько эффективно использование большого количества потоков. Например, порядка тысячи.

в общем случае - очень неэффективно. особенно "порядка тысячи".
PM MAIL   Вверх
W4FhLF
Дата 1.4.2007, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


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

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



Цитата(ilyalyu @  1.4.2007,  14:16 Найти цитируемый пост)
2. Я использую в программе критические секции. Для того чтобы исключить недопонимание, отмечу, что число критических секций НЕ ЕСТЬ число входов/выходов из критической секции (т.е. критическая секция может быть одна, а число входов/выходов много). Так вот вопрос в следующем. (1) Насколько критичным для скорости выполнения программы является использование большого количества критических секций (допустим порядка 1000). (2) Тот же вопрос, но уже относительно входов/выходов из критическую секцию. Например, насколько замедлится программа, если входы/выходы будут происходить через каждые 10 строчек (при этом считаем, что медленных операций, типа чтения/записи в файл, там нет).


Ну как сказать, смотря, что ты вкладываешь в понятия "быстро" и "медленно". Критические секции юзермодный механизм синхронизации, т.е. переходов между уровня привелегий не будет, это уже плюс. А в остальном ну выделяется память системой, заполняется структура, далее сравнивается и в конце-концов освобждается. Сам прикидывай насколько это быстро. 
А какие операции ты выполняешь в секции? Если тебе нужно выполнить только чтение/запись в память, то может обойдёшься стандартными Inetlocked-функциями?

Добавлено через 2 минуты и 18 секунд
Цитата(ilyalyu @  1.4.2007,  14:42 Найти цитируемый пост)
Кстати, забыл спросить. А насколько эффективно использование большого количества потоков. Например, порядка тысячи. Например, не окжется ли, что переключение между потоками будет занимать 90% процессорного времени и т.д.


Если ты выполняешь синхронные действия, т.е. действия, которые не заставляют ждать ответа от сторонних приложений или, к примеру, из сокета, то даже 2 потока не дадут тебе прироста больше 10%, а уж 1000 вообще сведут на 0 и даже угонят в минус, твою оптимизацию.


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
ilyalyu
Дата 1.4.2007, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



dumb, W4FhLF, спасибо за коментарии.

Для того чтобы всем облегчить жизнь, напишу, для чего я использую потоки. Я пишу чат-сервер с использованием сокетов. Соответственно, большинство потоков просто ожидают данных из сокета. Весь вопрос в том, что происходит в это время. Я в меру своей необразованности представляю это так: переодически происходит переключение между разными потоками и они проверяют, не поступило ли данных. Соответственно, время расходуется на переключение и проверку сокетов. Вот вопрос, если брать в расчет только эти операции, то сколько потоков одновременно можно потянуть. Дело в том, что я уже написал чат-сервер на PHP без потоков, но он уже при 100 юзерах онлайн грузит процессор на 30% и более. Мне надо, чтобы сервер нормально работал при 1000+ юзерах онлайн.

Вопрос насчет критических секций разрешился с помощью тестирования. 2,5 миллиона входов и выходов за одну секунду на 667мгц. Думаю, мне этого вполне достаточно smile
PM MAIL   Вверх
ilyalyu
Дата 1.4.2007, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Теперь протестировал работу большого количества потоков. Код приблизительно такой:

Код

function g(p: Pointer): Longint;
begin
  while true do begin
    Sleep(1000);
    EnterCriticalSection(__CSIOScreen);
    LeaveCriticalSection(__CSIOScreen);
  end
end;

for i := 1 to 10000 do begin BeginThread(g);


Внутри потоков ничего не происходит, они просто "просыпаются" раз в секунду. Оказалось, что на создание 10 тысяч потоков уходит 30 секунд. То есть 300 потоков в секунду (что-то долго...). После этого программа потребляет 2% от 677мгц. То есть одновременно могут функционировать порядка 500 тысяч потоков. Памяти все это занимает 90мб, то есть 9кб на поток.
PM MAIL   Вверх
Бонифаций
Дата 1.4.2007, 20:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



  • По умолчанию каждый трид (в линуксе) выделяет 2М памяти под стек. То есть на 1000 клиентов вам понадобится около 2 гиг памяти только на то чтобы ваша программа как-то дышала.. Если у вас физической памяти меньше, то наличие такого количества тридов приведет к дикому свапированию памяти. 
  •  По умолчанию в glibc внутренние структуры заточены под максимум 1024 трида. Если у вас их будет больше, необходима перекомпиляция glibc. Это бооольшая жывопырка
  •  Обычно такие задачи с большим количеством вялых клиентов решаются при помощи асинхронной работы сокетов. Смотрите функции select и poll



--------------------
 Бонифаций.
 
PM MAIL ICQ Skype GTalk Jabber YIM   Вверх
ilyalyu
Дата 1.4.2007, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Бонифаций, спасибо за коментарий. Посмотрел по интернету, что пишут про поддержку потоков и пришел к предварительному выводу, что под Windows лучше использовать потоки (и это вроде бы подтверждается моими тестами - 10000 потоков потребляют всего 1-2% процессорного времени), а под Linux лучше использовать операцию Select.

Вопрос - насколько этот вывод правильный?

Что касается размера стека, то его можно задавать в функции BeginThread. А разве под Linux стек не растет динамически, как под Windows? Вот уж не ожидал. На Windows обычно всех собак вешают, а выходит, что и поддержка потоков у него лучше, и о размере стека в отличие от Linux не приходится беспокоиться...
PM MAIL   Вверх
Бонифаций
Дата 1.4.2007, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



PS PS. то что я присал относится к linuxthread. В NPTL другая кухня. А для чатов лучше использовать select в любом случае.



--------------------
 Бонифаций.
 
PM MAIL ICQ Skype GTalk Jabber YIM   Вверх
ilyalyu
Дата 1.4.2007, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Я пишу на Free Pascal. Пока я там нашел select только под Linux. Под Windows его просто нет или я пока не нашел. Но я еще поищу. Спасибо.
PM MAIL   Вверх
Void
Дата 1.4.2007, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

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



ilyalyu, создал 10000 потоков? Отлично, а теперь посмотри в диспетчере задач, сколько потоков у твоего процесса. Окажется чуть более двух тысяч. Это предел для процесса: стеки потоков занимают всё адресное пространство. Своп не начинается, потому что память не закоммичена.
Лучше не использовать модель «один клиент — один поток», это ж не Эрланг всё-таки.
В Windows для таких вещей рекомендуется использовать пулы потоков.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
ilyalyu
Дата 1.4.2007, 23:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



В диспечере задач я такой информации не нашел., но при проверке с помощью приведенного ниже кода выяснилось, что создается порядка 8000 потоков, т.е. действительно есть ограничение. 

Код

function g(p: Pointer): Longint;
begin
  EnterCriticalSection(CS);
  Count := Count+1;
  LeaveCriticalSection(CS);
  while True do Sleep(1000);
end;

for i := 1 to 10000 do BeginThread(g);
writeln(Count);


Вашу идею я понял. Можно проверять сокеты на наличие данных, а затем уже обрабатывать их внутри нескольких потоков. Я согласен, что это наиболее оптимальное решение. Вот только найду, где select под windows... Точнее я уже нашел - в юните winsock. Осталось теперь только help к ней найти smile

Это сообщение отредактировал(а) ilyalyu - 1.4.2007, 23:15
PM MAIL   Вверх
dumb
Дата 2.4.2007, 02:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

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



Цитата(ilyalyu @  1.4.2007,  23:14 Найти цитируемый пост)
for i := 1 to 10000 do BeginThread(g);
writeln(Count);

все твои "замеры" некорректны(про некоторые моменты уже сказали) или просто содержат ошибку - как процитированный кусок.
настоятельно советую прочитать несколько статей про многопоточность.
начать можно с этой статьи.

Цитата(ilyalyu @  1.4.2007,  19:27 Найти цитируемый пост)
То есть одновременно могут функционировать порядка 500 тысяч потоков.

сильно сомневаюсь. даже если такое кол-во удастся запустить, то вся система будет "пытаться выжить", причем не факт, что это ей удастся. smile
PM MAIL   Вверх
Pulse69
Дата 2.4.2007, 09:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 28.4.2006
Где: Хабаровск

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



Цитата(ilyalyu @  1.4.2007,  19:27 Найти цитируемый пост)
То есть одновременно могут функционировать порядка 500 тысяч потоков.

Очень вряд ли что такое число потков в реальной работе не подвесит Вашу систему.
Модель "один клиент - один поток" является самой неэффективной. Вы вряд ли сможете 
её использовать если число подключенных клиентов превысит 500-600.
Единственный способ в Windows обрабатывать тысячи клиентов - это IO Completion Ports.
По разным оценкам, приложение на основе IOCP могут обсуживать до 32000 клиентов.
Если Вам нужно действительно эффективное приложение, стоит всерьёз рассмотреть
возможность использования IOCP. Поверьте, разница действительно впечатляет.

Для Winsock начать можно с этой статьи.
http://msdn.microsoft.com/msdnmag/issues/1000/Winsock/
--------------------
Ctrl+Alt+Reset 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

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

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

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

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

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


 




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


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

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