Использование WinApi для создания пула потоков

Форум для изучающих FPC и их учителей.

Модератор: Модераторы

Использование WinApi для создания пула потоков

Сообщение stesl » 30.03.2018 05:53:40

Приветствую Вас, приветствуйте новичка.
Вопрос в следующем, как всегда есть задание - что то там сделать (суть не важна)
При помощи пула из M потоков (M ≤ N), используя системный пул потоков или асинхронные потоки ввода/вывода.

Как?
При помощи массива из M потоков (M ≤ N), используя для синхронизации объект ядра — семафор.

мы с преподавателем осилили.

Весь парадокс ситуации, что конечно сделать это предлагается на С/С++, однако меня забыли предварительно обучить этим языкам. Преподаватель был вынужден согласиться, что изучать язык, для выполнения лабораторной работы, прямо не связанной с программированием (Теория вычислительных процессов) - не комильфо.
.NET в FreePascal недоступна. Изучать PascalABC.Net я также отказался.

Так есть у кого то опыт организации такого пула? Может есть желание мозг поднапречь? Моя беда, то, что я не знаю языки. От англ до С. И не могу пользоваться примерами написанными на С.

Вот что есть в УМП
В API Windows пула потоков, как такового, нет. Для создания пула рабочих потоков можно вручную создавать массив потоков вызовом функции CreateThread, а затем ожидать окончания их выполнения вызовом функции WaitForMultipleObjects(Ex) или MsgWaitForMultipleObjects(Ex). Для создания очереди асинхронных операций используется функция QueueUserAPC. В качестве сигнальных объектов могут выступать как сами процессы и потоки, так и семафоры, мьютексы, таймеры и события (табл. 3.5, п. 3.2.3). Также для организации пула потоков можно использовать порты завершения ввода/вывода (п. 3.2.3.5).


Если есть что то полезное в этом обрывке, могу привести и эти пп.
stesl
новенький
 
Сообщения: 31
Зарегистрирован: 30.03.2018 05:40:02

Re: Использование WinApi для создания пула потоков

Сообщение Дож » 30.03.2018 21:19:28

Казалось бы, фрагмент «В API Windows пула потоков, как такового, нет. Для создания пула рабочих потоков можно вручную создавать массив потоков вызовом функции CreateThread, а затем ожидать окончания их выполнения вызовом функции WaitForMultipleObjects(Ex) или MsgWaitForMultipleObjects(Ex).» исчерпывающе отвечает на вопрос о том, как делать. В чём трудности?
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 708
Зарегистрирован: 12.10.2008 16:14:47

Re: Использование WinApi для создания пула потоков

Сообщение Pavia » 30.03.2018 21:29:56

Пул потоков.
Не хочу лить воду. А в проектировании так всегда или почти всегда. Поэтому остановимся на конкретике.

Зачем он нужен?
Автоматизация управления потоками.
Разделение управления и обработчиков.
Повышение производительности.
Балансировка потоков.
Когда не следует использовать пул потоков?
Когда есть длинные задачи.
Приоритеты задач
Необходимо иметь стабильную идентификацию, сопоставленную с потоком, или назначить поток задаче.

Автоматизация. Пользователю пулом потоков не нужно заботиться о создание и уничтожении потоков.
Разделение управления и обработчиков. Пулом потоков за счёт инкапсуляции позволяет избежать досадных ошибок. Защищая данные передаваемые в поток и сами потоки от возможных случайных ссылок на уничтоженные объекты(потоки и данные).
Замечание ! Такой подход не означает, что вы можете забыть о безопасности данных. Просто он гарантирует целостность их на входе в задачу и на выходе из задачи. Но если вы будете их менять по ходу выполнения задачи, то вы сможете нарваться на неприятности.
Для коротких задач не требуется каждый раз создавать поток.
Балансировка потоков. Числом различных задач можно балансировать нагрузку. Ставя в очередь нужное количество задач мы можем получить нужный процентное соотношение.

Если хочется то можно
Когда есть длинные задачи. Вы можете разбить их на короткие и тогда вы сможет в любой момент прервать длинную задачу.

Приоритеты задач. Пул потоков не предусматривает очерёдность исполнения задач.
Но если их ввести в модификацию, то возникнут трудности с повышением производительности. Но в принципе есть решения допускающее такой подход.
Необходимо иметь стабильную идентификацию, сопоставленную с потоком, или назначить поток задаче. Редкий случай, когда надо закрепить за потоком нужные данные.
Замечание! Фрагментация памяти. Во избежание фрагментации память должна выделяться до того как пул потоков начнёт работать. Либо же вы должны использовать сборку мусора и дефрагментатор.

Как пул потоков планирует работы потоков?
Поток опрашивает очередь в течении NonSleepTime. Если не находит задач то засыпает.
Если пул- потоков обнаруживает что потоки не используются более TimeLive=CoiffecienLive* NonSleepTime то поток уничтожается.

Новые потоки создаются если замечено нехватка рабочих потоков. Потоки не забрали ни одну задачу за WorkTime.
Если задач нет, то потоки либо засыпают, либо уничтожаются. Если потоков меньше минимума то они спят если больше уничтожаются.

http://embarcadero.newsgroups.archived.at/public.delphi.language.delphi.win32/201001/1001126520.html

http://msdn.microsoft.com/en-us/library/windows/desktop/ms683194(v=vs.85).aspx

http://msdn.microsoft.com/ru-ru/library/0ka9477y(v=vs.110).aspx

http://rsdn.ru/forum/delphi/1181461.all

Добавлено спустя 7 минут 29 секунд:
stesl писал(а):Как?

А задача где? Прочтите в интернете как правильно задавать вопросы. Не описывайте что делали или что сделали описывайте что надо сделать. Иначе вас непонятно.
Аватара пользователя
Pavia
постоялец
 
Сообщения: 214
Зарегистрирован: 07.01.2011 12:46:51

Re: Использование WinApi для создания пула потоков

Сообщение runewalsh » 30.03.2018 22:06:30

>В API Windows пула потоков, как такового, нет.
Есть. :\

QueueUserWorkItem — для всех версий.

CreateThreadpoolWork/SubmitThreadpoolWork/CloseThreadpoolWork — для Vista+, сложнее, но больше возможностей: например, можно подождать завершения определённого задания функцией WaitForThreadpoolWorkCallbacks, а чтобы достичь того же с QueueUserWorkItem, придётся самому вести счётчик исполняемых заданий и/или выставлять событие. Как и в .NET, потоки пула не препятствуют завершению процесса при выходе из main, поэтому ждать завершения в общем случае необходимо.

В методичке полно неверной информации, как посмотрю («иногда система инвертирует приоритеты, чтобы разрешить конфликты типа deadlock»).
Аватара пользователя
runewalsh
постоялец
 
Сообщения: 406
Зарегистрирован: 27.04.2010 00:15:25

Re: Использование WinApi для создания пула потоков

Сообщение serbod » 31.03.2018 00:16:22

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


Зачем тебе теория вычислительных процессов, если языки не знаешь и знать не хочешь? Иди руками работай.
Аватара пользователя
serbod
постоялец
 
Сообщения: 322
Зарегистрирован: 16.09.2016 11:03:02
Откуда: Минск

Re: Использование WinApi для создания пула потоков

Сообщение olegy123 » 31.03.2018 07:27:40

stesl писал(а):Так есть у кого то опыт организации такого пула? Может есть желание мозг поднапречь? Моя беда, то, что я не знаю языки. От англ до С. И не могу пользоваться примерами написанными на С.

В паскале называется это все Parallel programming
http://wiki.freepascal.org/Category:Par ... rogramming

конкретно:
http://wiki.freepascal.org/Parallel_procedures

Добавлено спустя 29 минут 56 секунд:
https://github.com/BeRo1985/pasmp
olegy123
энтузиаст
 
Сообщения: 989
Зарегистрирован: 25.02.2016 12:10:20

Re: Использование WinApi для создания пула потоков

Сообщение stesl » 31.03.2018 13:18:21

Дож писал(а):исчерпывающе отвечает на вопрос о том, как делать. В чём трудности?

Трудности в том, что нужно найти метод, или доказать преподавателю, что метода нет, а значит и задание невыполнимо. По крайней мере в FP
Метод создания МАССИВА потоков уже освоен в предыдущем задании. Цитата говорит, что можно создать псевдопул, т.е. массив. Но как им управлять?
FP знает QueueUserAPC?
Pavia писал(а):А задача где? Прочтите в интернете как правильно задавать вопросы. Не описывайте что делали или что сделали описывайте что надо сделать. Иначе вас непонятно.

Столько текста, как Вы, я не осилю написать? Какая задача? Вопрос стоит предельно ясно: можно ли в FP средствами WinAPI создать пул потоков. Если да, то как?
И про языки, в том чисде английский я тоже написал
runewalsh писал(а):Есть. :\

Спасибо, попытаюсь изучить, или преподаватель пусть поможет.
runewalsh писал(а): В методичке полно неверной информации, как посмотрю («иногда система инвертирует приоритеты, чтобы разрешить конфликты типа deadlock»).
В какой методичке?
serbod писал(а):Зачем тебе теория вычислительных процессов, если языки не знаешь и знать не хочешь? Иди руками работай.

Как много тут самоутверждающихся... Отвечу - мне нахрен не нужна ТВП, нужен лишь диплом. А работаю руками инженером АСУТП. И спокойно себе ваяю на FBD,ST,IL и не парюсь о потоках. Так что какие то языки я знаю. Паскаль в их числе
olegy123 писал(а):В паскале называется это все Parallel programming

Спасибо, буду знать. Английский - плохо
stesl
новенький
 
Сообщения: 31
Зарегистрирован: 30.03.2018 05:40:02

Re: Использование WinApi для создания пула потоков

Сообщение Дож » 31.03.2018 14:52:11

Цитата говорит, что можно создать псевдопул, т.е. массив.

Массив — это один из способов реализовать пул (любой пул, не только потоков). Почему получится «псевдопул», а не обычный пул, я не очень понимаю.
Но как им управлять?

Вы не назвали какие операции с пулом вам нужны, поэтому лучший ответ на этот вопрос — легко и непринуждённо :)

Операцию ожидания завершения задач в пуле, как следует из процитированного фрагмента, можно реализовать при помощи функции WaitForMultipleObjects (или MsgWaitForMultipleObjects).

Ещё есть WaitForThreadTerminate. Ниже про QueueUserWorkItem и Parallel programming тоже дело говорят.
FP знает QueueUserAPC?

Из FP можно объявить и вызвать любую WinApi функцию.
Последний раз редактировалось Дож 31.03.2018 15:37:23, всего редактировалось 1 раз.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 708
Зарегистрирован: 12.10.2008 16:14:47

Re: Использование WinApi для создания пула потоков

Сообщение stesl » 31.03.2018 15:14:16

Дож писал(а):Массив — это один из способов реализовать пул (любой пул, а только потоков). Почему получится «псевдопул», а не обычный пул, я не очень понимаю.

Мне трудно спорить, возможно, с профи, но из того, что я понял, и того что написали выше - системный пул потоков, и массив потоков, созданный вручную это очень разные вещи.
Дож писал(а):Вы не назвали какие операции с пулом вам нужны, поэтому лучший ответ на этот вопрос — легко и непринуждённо :)

натравливать на одну и ту же функцию, ограждая критическую секцию (не сам объект ядра, а похожее на это определение, место в коде) семафором. Выполнить эту ф-цию сначала в один поток. Потом в несколько и показать разницу во времени обработки.
Дож писал(а):Из FP можно объявить и вызвать любую WinApi функцию.

почему тогда при попытке компиляции ругань идет именно на, по идее терминал QueueUserAPC. Не знает компилятор такой строки
stesl
новенький
 
Сообщения: 31
Зарегистрирован: 30.03.2018 05:40:02

Re: Использование WinApi для создания пула потоков

Сообщение Дож » 31.03.2018 15:28:24

Код: Выделить всё
uses
  windows;

function QueueUserAPC(pfnAPC: Pointer; hThread: HANDLE; dwData: ULONG_PTR): DWORD; stdcall; external 'Kernel32.dll';

begin
  Writeln(QueueUserAPC(nil, 0, 0));
end.

Код: Выделить всё
D:\data\temp>fpc tp.pas
Free Pascal Compiler version 3.0.4 [2017/10/06] for i386
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling tp.pas
Linking tp.exe
8 lines compiled, 0.3 sec, 25424 bytes code, 1268 bytes data
Последний раз редактировалось Дож 31.03.2018 16:57:02, всего редактировалось 1 раз.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 708
Зарегистрирован: 12.10.2008 16:14:47

Re: Использование WinApi для создания пула потоков

Сообщение stesl » 31.03.2018 15:54:58

Ну теперь пришла пора сознаться, что это не я пытался что то сделать с этой ф-цией. Это преподаватель пожаловался, что у него не компилится чего то там.
ПРАСТИТИ! А то щас закидаете :)
Друг, а ты не мог бы по полочкам разложить, что за параметры у этой ф-ции, msdn написан на англ и С. Почему ты ее вызываешь как то интересно через writeln. Что там за кернел.
И вообще, что делать дальше? Что мы получаем в рез-тате вызова этой ф-ции?

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

Добавлено спустя 4 минуты 6 секунд:
Понял. С тлф читаю, пишу, не все видно понятно. То есть ты выводишь рез-тат ф-ции, описанной ранее. Но разве это не твоя, пользовательская ф-ция? Или экстернал - длл и говорит о том, что это системная ф-ция
stesl
новенький
 
Сообщения: 31
Зарегистрирован: 30.03.2018 05:40:02

Re: Использование WinApi для создания пула потоков

Сообщение Снег Север » 31.03.2018 16:07:26

stesl писал(а):Или экстернал - длл и говорит о том, что это системная ф-ция
Именно это и говорит - вызвать функцию из системной библиотеки Kernel32.dll
Аватара пользователя
Снег Север
энтузиаст
 
Сообщения: 1177
Зарегистрирован: 27.11.2007 16:14:47

Re: Использование WinApi для создания пула потоков

Сообщение stesl » 31.03.2018 16:59:01

Снег Север писал(а):Именно это и говорит - вызвать функцию из системной библиотеки Kernel32.dll


Очень ценное знание. Спасибо Вам обоим. Позже, если интересно, покажу как мы запускали поток и семафор. А в этом файле весь API и находится?
stesl
новенький
 
Сообщения: 31
Зарегистрирован: 30.03.2018 05:40:02

Re: Использование WinApi для создания пула потоков

Сообщение runewalsh » 31.03.2018 17:05:45

stesl писал(а):В какой методичке?

В той, фрагмент которой приведён в первом посте. Она гуглится и там много странностей.
Алсо, пример с QueueUserWorkItem + RTLEvent:
Код: Выделить всё
{$mode objfpc} {$h+}
uses
   Windows, SysUtils;

   function QueueUserWorkItem(func: LPTHREAD_START_ROUTINE; Context: pointer; Flags: ULONG): BOOL; stdcall; external kernel32;

var
   runningTasks: integer; // = 0
   allTasksCompleted: PRTLEvent;

   procedure PrepareTaskQueuing;
   begin
      if InterlockedIncrement(runningTasks) = 1 then RTLEventResetEvent(allTasksCompleted);
   end;

   procedure NoteTaskCompleted;
   begin
      if InterlockedDecrement(runningTasks) = 0 then RTLEventSetEvent(allTasksCompleted);
   end;

   procedure Task(param: pointer); stdcall;
   begin
      writeln('Задача ' + IntToStr(PtrUint(param)) + ' начата (поток #' + IntToStr(GetCurrentThreadID) + ')');
      Sleep(1500);
      writeln('Задача ' + IntToStr(PtrUint(param)) + ' выполнена (поток #' + IntToStr(GetCurrentThreadID) + ')');
      NoteTaskCompleted;
   end;

begin
   allTasksCompleted := RTLEventCreate;
   PrepareTaskQueuing; writeln('Добавление задачи 1.'); QueueUserWorkItem(@Task, pointer(1), 0);
   Sleep(1000);
   PrepareTaskQueuing; writeln(LineEnding + 'Добавление задачи 2.'); QueueUserWorkItem(@Task, pointer(2), 0);
   Sleep(1000);
   PrepareTaskQueuing; writeln(LineEnding + 'Добавление задачи 3.'); QueueUserWorkItem(@Task, pointer(3), 0);
   Sleep(1000);
   PrepareTaskQueuing; writeln(LineEnding + 'Добавление задачи 4.'); QueueUserWorkItem(@Task, pointer(4), 0);

   writeln(LineEnding + 'Ожидание завершения всех задач...');
   RTLEventWaitFor(allTasksCompleted);
   RTLEventDestroy(allTasksCompleted);
   writeln('OK!');
   readln;
end.
Последний раз редактировалось runewalsh 31.03.2018 18:01:12, всего редактировалось 1 раз.
Аватара пользователя
runewalsh
постоялец
 
Сообщения: 406
Зарегистрирован: 27.04.2010 00:15:25

Re: Использование WinApi для создания пула потоков

Сообщение Дож » 31.03.2018 17:21:16

У меня изначально в коде была ошибка, нужно ещё stdcall указать.
Друг, а ты не мог бы по полочкам разложить, что за параметры у этой ф-ции, msdn написан на англ и С.

pfnAPC — указатель на Вашу (пользовательскую) функцию с прототипом вида
Код: Выделить всё
procedure APCProc(dwParam: ULONG_PTR); stdcall;
begin
  // тут код
end;

hThread — айдишник треда, в котором функцию нужно запустить, dwData — аргумент, который будет в эту функцию передан (ULONG_PTR — численный тип, но его можно кастовать в и из Pointer).
Почему ты ее вызываешь как то интересно через writeln.

Я лишь демонстрировал, что «Из FP можно объявить и вызвать QueueUserAPC.», для этих целей я мог бы передать любые параметры.
Что там за кернел.

https://ru.wikipedia.org/wiki/Kernel32.dll
https://ru.wikipedia.org/wiki/Windows_API
Ты спросишь, а какого ты вообще про эту ф-цию спрашиваешь?

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

Без понятия :)
Что мы получаем в рез-тате вызова этой ф-ции?

Функция помещается в очередь на вызов в определённом потоке.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 708
Зарегистрирован: 12.10.2008 16:14:47

След.

Вернуться в Обучение Free Pascal

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

Рейтинг@Mail.ru