Конференция "WinAPI" » Странный deadlock [D7, WinXP]
 
  • ага (16.01.08 06:17) [20]

    >Но и ты на меня не обижайся, пожалуйста!

    Да вроде не на что:)

    >Ну, попробуй представить,

    Попробовал - не получается. Это я так шучу, если че:))

    >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-й элемент обработать главным потоком, а потому уже ждать остальные. Элементарно, если вынести обработку в отдельную функцию.

    >Иногда я искренне удивляюсь,

    А че удивляться-то? Отвечает не автоматы, обычные люди. И говорят они то, что считают нужным они сами, а не спрашивающий. Хотя бы потому, что зачастую видят проблему куда ширше, чем задавший вопрос. Имеют право, разве нет?
  • ага (16.01.08 06:27) [21]

    >А это реализация вот этого

    Ан нет, не совсем. Медленнее будет, чем только со стартерам, но отдельным для каждого потока
  • ага (16.01.08 07:02) [22]
    А можно и с одним стартером

    unit Unit1;
    // Delphi-7, MS Windows XP SP2, CPU Intel Pentium-4 3.0 GHz

    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

    {$R *.dfm}

    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 использовать.
  • ага (16.01.08 07:10) [23]
    :))) Да и 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]
  • ага (16.01.08 08:35) [24]
    Поспешишь - людей насмешишь:( Фигню я написал в последних постах. Сейчас вернулся, посмотрел спокойно - полная фигня. Не будет остановки потоков в WaitForSingleObject (startEvent,INFINITE), эвент-то не сброшен. В общем, не обращай на это внимание.

    Быстрее всего будет при использовании CompletionPort или, если без порта, при отдельном стартере на каждый поток.
  • mt2 (16.01.08 22:57) [25]
    >Отвечает не автоматы, обычные люди. И говорят они то, что считают нужным они сами, а не спрашивающий. Хотя бы потому, что зачастую видят проблему куда ширше, чем задавший вопрос. Имеют право, разве нет?<

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

    >Нормальное решение, если не учитывать, что будет работать медленнее, чем в варианте, когда число потоков = числу процессоров. Это я из вредности:)) Ну не верю я, что оно когда-нить будет работать на 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 стабильно повторяется. Надо будет разбираться, почему.
  • ага (17.01.08 07:27) [26]

    >ты говоришь правильные и хорошо известные вещи

    Если правильные и хорошо известные, так почему тогда "я искренне удивляюсь"? Да ладно, фиг с ним.

    >Право имеют, а вот что видят проблему шире, не факт.

    Конечно не факт, ты говоришь правильные и хорошо известные вещи:)) Бывают исключения, но в большинстве случаев это все-же так. У меня большой форумный опыт, из него и сделал обобщение. К сожалению форумы, изначельно задуманные как профессиональные клубы для взимопомощи и консультаций c коллегами, постепенно превратились в ликбез, где одна группа практически только задает вопросы, а другая, относительно узкая, - только отвечает:((

    А по поводу конкурсов - да не прикалывают они меня, всяческие конкурсы, жаль на них время тратить. К тому же там все на JavaScript, а он у меня отключен из прынципу. А уж споры на тему, какой язык толще...э-э, то бишь круче - это ваще без меня.

    >не понял, что это оригинальный модуль, а то бы сказал, что не подойдет из-за заморочек с копирайтом

    Да какой там нафиг копирайт:))) Три вызова апишных функций, завернутых в элементарный класс:)) Ну используй эти функции напрямую, без класса, никакого копирайта:)
  • mt2 (17.01.08 22:20) [27]

    > ага   (17.01.08 07:27) [26]
    >
    > >ты говоришь правильные и хорошо известные вещи
    >
    > Если правильные и хорошо известные, так почему тогда "я
    > искренне удивляюсь"? Да ладно, фиг с ним.


    Да я не тому удивляюсь, а тому, когда спрашиваешь про одно, а в ответ слышишь  правильное, но хорошо известное… Да ладно, фиг с ним:)))


    >
    > >Право имеют, а вот что видят проблему шире, не факт.
    >
    > Конечно не факт, ты говоришь правильные и хорошо известные
    > вещи:)) Бывают исключения, но в большинстве случаев это
    > все-же так. У меня большой форумный опыт, из него и сделал
    > обобщение. К сожалению форумы, изначельно задуманные как
    > профессиональные клубы для взимопомощи и консультаций c
    > коллегами, постепенно превратились в ликбез, где одна группа
    > практически только задает вопросы, а другая, относительно
    >  узкая, - только отвечает:((


    У меня опыт Инета с 1987 г ;)
    На счет ликбеза – 1) сами виноваты – чуть посложнее задача и что, кроме тебя и меня много еще конструктивных мнений в этом топике? Кому-то, видимо, нравится отвечать только на очевидные вопросы… 2) может, мне показалось, но и у тебя иногда проскальзывают менторские нотки (у других больше) – мне по-фигу, но не всем коллегам такое будет приятно, вот никто никого (из группы «только отвечает») ни о чем и спрашивать не хочет, чтобы за чайника не приняли – а ведь ежику ясно, что если один нечайник разобрался в апишной хххХхххХхх и потратил на это дня два, а другой не тратил и спросил, он бы может всего день потратил сам, но стоит ли каждому изобретать велосипед? Но почему-то к спросившему сразу относятся как к чайнику. 3) В конкурсе общение на более высоком уровне. Никто пока не пытается никого учить тому, что такое «мать» и родина и как их любить…Уникальная возможность общаться без названных форумных заморочек. Но, впрочем, твое дело, раз не прикалывают.


    > А по поводу конкурсов - да не прикалывают они меня, всяческие
    > конкурсы, жаль на них время тратить. К тому же там все на
    > JavaScript, а он у меня отключен из прынципу. А уж споры
    > на тему, какой язык толще...э-э, то бишь круче - это ваще
    > без меня.


    На мой взгляд, JavaScript лучше Java тем, что от первого меньше вреда, но я тоже когда могу отключаю. От них много зла и гадостей.

    «Кто толще» - хорошая стартовая точка для выхода на нетривиальные вопросы, а то начинаешь с чего-то конкретного и получается в лучшем случае ликбез. Конечно, как всегда, все зависит от публики, чаще всего ничего не выходит.


    > >не понял, что это оригинальный модуль, а то бы сказал,
    > что не подойдет из-за заморочек с копирайтом
    >
    > Да какой там нафиг копирайт:))) Три вызова апишных функций,
    >  завернутых в элементарный класс:)) Ну используй эти функции
    > напрямую, без класса, никакого копирайта:)


    ОК. Позже разберусь. А все-таки скажи, чем он так хорош? У тебя есть опыт использования? Какие-нибудь сравнения?

    И еще, возвращаясь к решению, но не отменяя сказанного: еще одна идея – решение просто редуцируется под число процессоров, т.е. можно из двух потоков сделать один:

    procedure TtestThread41.Execute;
    // similar TtestThread42.Execute, …,TtestThread21.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 процессоров.
  • Leonid Troyanovsky © (17.01.08 23:07) [28]

    > mt2   (17.01.08 22:20) [27]

    > У меня опыт Инета с 1987 г ;)
    > На счет ликбеза – 1) сами виноваты – чуть посложнее задача
    > и что, кроме тебя и меня много еще конструктивных мнений
    > в этом топике? Кому-то, видимо, нравится отвечать только
    > на очевидные вопросы… 2) может, мне показалось, но и у тебя
    > иногда проскальзывают менторские нотки (у других больше)
    > – мне по-фигу, но не всем коллегам такое будет приятно,
    > вот никто никого (из группы «только отвечает») ни о чем
    > и спрашивать не хочет, чтобы за чайника не приняли

    А ты воздержись от самохваления и перейди к суровой правде жизни.  
    Например, потрудись формулировать вопросы надлежащим образом.

    Хотя,  если уж за 20 лет общения не постигнута даже такая простая
    вещь как сложность общения честных людей с анонимами, то, IMHO,
    трудно рассчитывать на успех и в этом деле.

    Ну, а рассуждения о редукции под число процессоров на фоне
    ненайденного источника AV выглядят, мягко говоря, нелепо.

    Да и книжечку б неплохо б было почитать хоть к.л.

    --
    Regards, LVT.
  • ага (18.01.08 18:54) [29]

    > А все-таки скажи, чем он так хорош?

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

    > У тебя есть опыт использования?

    Опыт есть, но не в таких масштабах, чтобы можно было привести впечатляющие цифры. Однако выигрыш достаточно заметен, если конечно остальным кодом его не сожрать.
  • mt2 (18.01.08 19:08) [30]

    > ага   (18.01.08 18:54) [29]
    >
    > > А все-таки скажи, чем он так хорош?
    >
    > Он имеет полную информацию о состоянии процессоров и на
    > ее основе строит макимально оптимальную стратегию управления
    > пулом потоков, выбирая оптимальное в данный текущий момент
    > количество активных потоков и по возможности избегая лишних
    > переключений контекстов. Особенно эфективен, когда потоки
    > выполняют какие-нито операции, связанные с ожиданием - дисковые
    > там, или коммуникативные. Сделать все это вручную было бы
    > черзвычайно трудно, если вообще возможно в user mode.
    > Наконец он просто удобен. Почитать о нем достаточно подробно
    > можно у Рихтера  в книге по W2k.
    >
    > > У тебя есть опыт использования?
    >
    > Опыт есть, но не в таких масштабах, чтобы можно было привести
    > впечатляющие цифры. Однако выигрыш достаточно заметен, если
    > конечно остальным кодом его не сожрать.


    Ok. Спасибо!
 
Конференция "WinAPI" » Странный deadlock [D7, WinXP]
Есть новые Нет новых   [134431   +15][b:0][p:0.003]