-
>Но и ты на меня не обижайся, пожалуйста!
Да вроде не на что:)
>Ну, попробуй представить,
Попробовал - не получается. Это я так шучу, если че:))
>1) отсутствует файл {$I CompVersionDef.inc}
Да там чисто дефайны версий компилера, свободно выбрасывается
>2) EAccessViolation в методе TCompletionPort.SetCompletion
Нет там никаких AV, я ж код запускал, прежде чем постить. И как раз на XP SP2, какое совпадение:) Ищи че сам накосячил. Ну на крайняк передавай реальную структуру вместо TOverlappedEx(nil^), хотя и без того всегда работало.
>Хотелось бы услышать мнения об этом решении
А это реализация вот этого:
>ага (14.01.08 22:17) [12] А я бы Suspend не использовал. Дал бы потокам еще по эвенту и пусть они их ждут вместо Suspend. А в главном вместо Resume взводил бы эти эвенты. Нормальное решение, если не учитывать, что будет работать медленнее, чем в варианте, когда число потоков = числу процессоров. Это я из вредности:)) Ну не верю я, что оно когда-нить будет работать на 8-процессорной тачке, хоть ты меня убей:)) А даже если их 8, процессоров-то - разумно запустить 7 потоков, а 8-й элемент обработать главным потоком, а потому уже ждать остальные. Элементарно, если вынести обработку в отдельную функцию.
>Иногда я искренне удивляюсь,
А че удивляться-то? Отвечает не автоматы, обычные люди. И говорят они то, что считают нужным они сами, а не спрашивающий. Хотя бы потому, что зачастую видят проблему куда ширше, чем задавший вопрос. Имеют право, разве нет?
-
>А это реализация вот этого
Ан нет, не совсем. Медленнее будет, чем только со стартерам, но отдельным для каждого потока
-
А можно и с одним стартером
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
public
end;
TTestThread = class(TThread)
constructor Create (CreateSuspended : Boolean; eventHnd : THandle; i : integer);
private
ind : integer;
syncEvent : THandle;
protected
procedure Execute; override;
end;
var
Form1: TForm1;
events : array [0..7] of THandle;
startEvent, finishEvent : THandle;
thr : array [0..7] of TTestThread;
stop : Boolean;
n : integer;
calc : array [1..8] of integer;
ThreadCounter: integer;
implementation
constructor TTestThread.Create (CreateSuspended : Boolean; eventHnd : THandle; i : integer);
begin
inherited Create (CreateSuspended);
syncEvent := eventHnd;
ind := i;
FreeOnTerminate := true;
end;
procedure TTestThread.Execute;
begin
repeat
WaitForSingleObject (startEvent,INFINITE); if 0 = InterLockedDecrement(ThreadCounter) then ResetEvent(startEvent);
inc(calc [ind]);
SetEvent (syncEvent); until stop;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i : integer;
begin
for i:=1 to 8 do
calc [i] := 0;
stop := false;
n := 0;
repeat
inc (n);
ThreadCounter:= 8;
SetEvent (startEvent); waitForMultipleObjects (8, @events, true, INFINITE); for i:=0 to 7 do
ResetEvent (events [i]);
until n=1000;
Memo1.Lines.Add('n= '+ intToStr(n));
for i:=1 to 8 do
Memo1.Lines.Add(intToStr(calc[i]));
end;
procedure TForm1.FormCreate(Sender: TObject);
var
i : integer;
begin
for i:=0 to 7 do
events [i] := CreateEvent (nil, true, false, PChar('testEvent'+intToStr(i)));
startEvent := CreateEvent (nil, true, false, 'startEvent');
finishEvent := CreateEvent (nil, true, false, 'finishEvent');
for i:=0 to 7 do
thr[i] := TTestThread.Create(true, events [i],i+1);
for i:=0 to 7 do
thr[i].Resume;
end;
end.
Это я правда не компилировал - нечем - но работать должно. А можно и PulseEvent использовать.
-
:))) Да и syncEvent можно один на всех
var
CompleteCounter: integer;
procedure TTestThread.Execute;
begin
repeat
WaitForSingleObject (startEvent,INFINITE); if 0 = InterLockedDecrement(ThreadCounter) then ResetEvent(startEvent);
inc(calc [ind]);
if 0 = InterLockedDecrement(CompleteCounter) then SetEvent (syncEvent); until stop;
end
procedure TForm1.Button1Click(Sender: TObject);
var
i : integer;
begin
for i:=1 to 8 do
calc [i] := 0;
stop := false;
n := 0;
repeat
inc (n);
ThreadCounter:= 8;
CompleteCounter:= 8;
SetEvent (startEvent); waitForSingleObject (CompleteEvent, INFINITE); ResetEvent (CompleteEvent);
until n=1000;
...
Здесь CompleteEvent - один эвент с ручным сбросом вместо массива events[0..7]
-
Поспешишь - людей насмешишь:( Фигню я написал в последних постах. Сейчас вернулся, посмотрел спокойно - полная фигня. Не будет остановки потоков в WaitForSingleObject (startEvent,INFINITE), эвент-то не сброшен. В общем, не обращай на это внимание.
Быстрее всего будет при использовании CompletionPort или, если без порта, при отдельном стартере на каждый поток.
-
>Отвечает не автоматы, обычные люди. И говорят они то, что считают нужным они сами, а не спрашивающий. Хотя бы потому, что зачастую видят проблему куда ширше, чем задавший вопрос. Имеют право, разве нет?<Право имеют, а вот что видят проблему шире, не факт. Проблема другая, и я о ней скажу, она может тебя заинтересовать. Но прежде, в общем, я с тобой не спорю, ты говоришь правильные и хорошо известные вещи: >Нормальное решение, если не учитывать, что будет работать медленнее, чем в варианте, когда число потоков = числу процессоров. Это я из вредности:)) Ну не верю я, что оно когда-нить будет работать на 8-процессорной тачке, хоть ты меня убей:)) А даже если их 8, процессоров-то - разумно запустить 7 потоков, а 8-й элемент обработать главным потоком, а потому уже ждать остальные. Элементарно, если вынести обработку в отдельную функцию. <Решая одну задачку, я решил попробовать в том числе и экстравагантное решение, и натолкнулся на казус, о котором мой первый пост. Мне показалось интересным этот казус обсудить. При этом, прежде всего, я обсуждал конкретный казус и узко ограничивал рамки обсуждения. А то мы бы так и проговорили про общеизвестные вещи, типа «число потоков = числу процессоров». Теперь, когда цель достигнута и казус разъяснился, можем поговорить и шире. Кстати, этот код в решение я включать, видимо, не буду (по тем же самым соображениям, которые ты высказал), хотя Интелу (для которого это делается) под силу взять любую из существующих в природе тачек –даже из тех, что нет в магазинах;) Но в любом случае, в отчете напишу, что в числе возможных опробовал и такое решение – за это дадут дополнительные баллы:) А теперь о конкретной задачке и о проблеме. Задачка эта конкурсная, подробнее см. – http://softwarecommunity-rus.intel.com/articles/rus/61032.htm - игра Жизнь, в альтернативном алгоритме, который задан в виде кода на С (исх.код можно выгрузить там же), его нужно распараллелить. Это 4-й тур, а всего их 12, примкнуть можно в любой момент. Вот и посмотри, может, тебя заинтересует, а то проблема… - Теперь о проблеме: проблема в том, что я там пока один на Дельфи пишу, хотя и успешно, в предыдущем туре с 11 места передвинулся на 8, при том, что за быстродействие мои решения получили максимальные баллы, но языки в неравном положении по отношению к С++ (или С-- :) подробнее можешь почитать пост на форуме конкурса: http://softwarecommunity-rus.intel.com/isn/Community/ru-RU/forums/thread/30220903.aspx И было бы лучше, если бы еще кто-то сильный на Дельфи был в конкурсе… В отношении CompletionPort – жаль, я сразу, когда ты упомянул, не понял, что это оригинальный модуль, а то бы сказал, что не подойдет из-за заморочек с копирайтом. Но все равно модуль меня заинтересовал, и я его посмотрю подробнее, только позже, когда сдам это задание, а то сейчас уже время поджимает – я ведь не только для конкурса пишу, еще и работа есть;)) Пока первые запуски прошли, как я написал. Т.е. {$I CompVersionDef.inc} я, конечно, удалил, хотя такие вещи меня всегда настораживают, а EAccessViolation стабильно повторяется. Надо будет разбираться, почему.
-
>ты говоришь правильные и хорошо известные вещи
Если правильные и хорошо известные, так почему тогда "я искренне удивляюсь"? Да ладно, фиг с ним.
>Право имеют, а вот что видят проблему шире, не факт.
Конечно не факт, ты говоришь правильные и хорошо известные вещи:)) Бывают исключения, но в большинстве случаев это все-же так. У меня большой форумный опыт, из него и сделал обобщение. К сожалению форумы, изначельно задуманные как профессиональные клубы для взимопомощи и консультаций c коллегами, постепенно превратились в ликбез, где одна группа практически только задает вопросы, а другая, относительно узкая, - только отвечает:((
А по поводу конкурсов - да не прикалывают они меня, всяческие конкурсы, жаль на них время тратить. К тому же там все на JavaScript, а он у меня отключен из прынципу. А уж споры на тему, какой язык толще...э-э, то бишь круче - это ваще без меня.
>не понял, что это оригинальный модуль, а то бы сказал, что не подойдет из-за заморочек с копирайтом
Да какой там нафиг копирайт:))) Три вызова апишных функций, завернутых в элементарный класс:)) Ну используй эти функции напрямую, без класса, никакого копирайта:)
-
> ага (17.01.08 07:27) [26] > > >ты говоришь правильные и хорошо известные вещи > > Если правильные и хорошо известные, так почему тогда "я > искренне удивляюсь"? Да ладно, фиг с ним.
Да я не тому удивляюсь, а тому, когда спрашиваешь про одно, а в ответ слышишь правильное, но хорошо известное… Да ладно, фиг с ним:))) > > >Право имеют, а вот что видят проблему шире, не факт. > > Конечно не факт, ты говоришь правильные и хорошо известные > вещи:)) Бывают исключения, но в большинстве случаев это > все-же так. У меня большой форумный опыт, из него и сделал > обобщение. К сожалению форумы, изначельно задуманные как > профессиональные клубы для взимопомощи и консультаций c > коллегами, постепенно превратились в ликбез, где одна группа > практически только задает вопросы, а другая, относительно > узкая, - только отвечает:((
У меня опыт Инета с 1987 г ;) На счет ликбеза – 1) сами виноваты – чуть посложнее задача и что, кроме тебя и меня много еще конструктивных мнений в этом топике? Кому-то, видимо, нравится отвечать только на очевидные вопросы… 2) может, мне показалось, но и у тебя иногда проскальзывают менторские нотки (у других больше) – мне по-фигу, но не всем коллегам такое будет приятно, вот никто никого (из группы «только отвечает») ни о чем и спрашивать не хочет, чтобы за чайника не приняли – а ведь ежику ясно, что если один нечайник разобрался в апишной хххХхххХхх и потратил на это дня два, а другой не тратил и спросил, он бы может всего день потратил сам, но стоит ли каждому изобретать велосипед? Но почему-то к спросившему сразу относятся как к чайнику. 3) В конкурсе общение на более высоком уровне. Никто пока не пытается никого учить тому, что такое «мать» и родина и как их любить…Уникальная возможность общаться без названных форумных заморочек. Но, впрочем, твое дело, раз не прикалывают. > А по поводу конкурсов - да не прикалывают они меня, всяческие > конкурсы, жаль на них время тратить. К тому же там все на > JavaScript, а он у меня отключен из прынципу. А уж споры > на тему, какой язык толще...э-э, то бишь круче - это ваще > без меня.
На мой взгляд, JavaScript лучше Java тем, что от первого меньше вреда, но я тоже когда могу отключаю. От них много зла и гадостей. «Кто толще» - хорошая стартовая точка для выхода на нетривиальные вопросы, а то начинаешь с чего-то конкретного и получается в лучшем случае ликбез. Конечно, как всегда, все зависит от публики, чаще всего ничего не выходит. > >не понял, что это оригинальный модуль, а то бы сказал, > что не подойдет из-за заморочек с копирайтом > > Да какой там нафиг копирайт:))) Три вызова апишных функций, > завернутых в элементарный класс:)) Ну используй эти функции > напрямую, без класса, никакого копирайта:)
ОК. Позже разберусь. А все-таки скажи, чем он так хорош? У тебя есть опыт использования? Какие-нибудь сравнения? И еще, возвращаясь к решению, но не отменяя сказанного: еще одна идея – решение просто редуцируется под число процессоров, т.е. можно из двух потоков сделать один: procedure TtestThread41.Execute;
begin
repeat
WaitForSingleObject (startEvent,INFINITE);
inc(calc [ind]); inc(calc [ind+1]);
SignalObjectAndWait(syncEvent,finishEvent,INFINITE,False);
SetEvent (syncEvent); until stop;
end; а можно из четырех один. Запрашиваем перед запуском потоков, сколько процессоров (можно у ОС, можно у пользователя – м.б. тот не хочет все занимать) и запускаем соответствующие потоки, и так достигается «число потоков = числу процессоров», имеют смысл 3 варианта на 2,4,8 процессоров.
-
> mt2 (17.01.08 22:20) [27] > У меня опыт Инета с 1987 г ;) > На счет ликбеза – 1) сами виноваты – чуть посложнее задача > и что, кроме тебя и меня много еще конструктивных мнений > в этом топике? Кому-то, видимо, нравится отвечать только > на очевидные вопросы… 2) может, мне показалось, но и у тебя > иногда проскальзывают менторские нотки (у других больше) > – мне по-фигу, но не всем коллегам такое будет приятно, > вот никто никого (из группы «только отвечает») ни о чем > и спрашивать не хочет, чтобы за чайника не приняли
А ты воздержись от самохваления и перейди к суровой правде жизни. Например, потрудись формулировать вопросы надлежащим образом.
Хотя, если уж за 20 лет общения не постигнута даже такая простая вещь как сложность общения честных людей с анонимами, то, IMHO, трудно рассчитывать на успех и в этом деле.
Ну, а рассуждения о редукции под число процессоров на фоне ненайденного источника AV выглядят, мягко говоря, нелепо.
Да и книжечку б неплохо б было почитать хоть к.л.
-- Regards, LVT.
-
> А все-таки скажи, чем он так хорош?
Он имеет полную информацию о состоянии процессоров и на ее основе строит макимально оптимальную стратегию управления пулом потоков, выбирая оптимальное в данный текущий момент количество активных потоков и по возможности избегая лишних переключений контекстов. Особенно эфективен, когда потоки выполняют какие-нито операции, связанные с ожиданием - дисковые там, или коммуникативные. Сделать все это вручную было бы черзвычайно трудно, если вообще возможно в user mode. Наконец он просто удобен. Почитать о нем достаточно подробно можно у Рихтера в книге по W2k.
> У тебя есть опыт использования?
Опыт есть, но не в таких масштабах, чтобы можно было привести впечатляющие цифры. Однако выигрыш достаточно заметен, если конечно остальным кодом его не сожрать.
-
> ага (18.01.08 18:54) [29] > > > А все-таки скажи, чем он так хорош? > > Он имеет полную информацию о состоянии процессоров и на > ее основе строит макимально оптимальную стратегию управления > пулом потоков, выбирая оптимальное в данный текущий момент > количество активных потоков и по возможности избегая лишних > переключений контекстов. Особенно эфективен, когда потоки > выполняют какие-нито операции, связанные с ожиданием - дисковые > там, или коммуникативные. Сделать все это вручную было бы > черзвычайно трудно, если вообще возможно в user mode. > Наконец он просто удобен. Почитать о нем достаточно подробно > можно у Рихтера в книге по W2k. > > > У тебя есть опыт использования? > > Опыт есть, но не в таких масштабах, чтобы можно было привести > впечатляющие цифры. Однако выигрыш достаточно заметен, если > конечно остальным кодом его не сожрать.
Ok. Спасибо!
|