На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! user posted image
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.

Соблюдайте общие правила форума

Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как запустить программу/файл? (и дождаться ее завершения)
5. Как перехватить API-функции, поставить hook? (перехват сообщений от мыши, клавиатуры - внедрение в удаленное адресное прстранство)
... (продолжение следует) ...

Внимание:
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки - бан.
Мат в разделе - бан на три месяца...

Полезные ссылки:
user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


Выразить свое отношение к модераторам раздела можно здесь: user posted image Rouse_, user posted image Krid

Модераторы: Rouse_, Krid
Страницы: (3) [1] 2 3  все  ( Перейти к последнему сообщению )  
> Sleep - что внутри?
    Бесконечный цикл со Sleep(1) почти не грузит процессор.
    Что там такого зашито внутри? Как это можно реализовать кроме как через Sleep?
      Цитата Jin X @
      Бесконечный цикл со Sleep(1) почти не грузит процессор.
      Довольно логично: задача Sleep'а - указать ОС, что "такой-то процесс не работает, можете заняться своими делами", что она и делает.
      Цитата Jin X @
      Как это можно реализовать кроме как через Sleep?
      Уточните, что подразумевается под словом 'это'? Если "загрузку ЦП", то можно банально в цикле считать x=cos(x) и загрузка будет выше крыши (но одно ядро, конечно). (Тривиальное распараллеливание загрузит все ядра).
        Цитата Jin X @
        Бесконечный цикл со Sleep(1) почти не грузит процессор.
        Что там такого зашито внутри?

        Во-первых, зашито само название функции - Sleep, т.е. поток "засыпает" (приостанавливается) на время >= указанного значения. Во-вторых, "зашита" специфика отсчета времени в ОС - счет ведется дискретно по прерываниям системного таймера со стандартным (дефолтным) интервалом в 1/64 сек = 15.625 мс. Отсюда и существенная разница Sleep со значением 0 и > 0. В любом случае вызов Sleep передает управление ОС, которая должна запустить следующий по очереди "простаивающий и готовый к исполнению" поток на данном процессоре. Но если система не загружена и таковых потоков нет, то при Sleep(0) управление практически сразу возвращается вызвавшему эту функцию потоку. А в случае Sleep(X > 0) ОС обязана выдержать интервал времени не менее заданного, но поскольку счет времени ведется дискретно, то возобновление исполнения потока происходит только по очередному тику сис.таймера, т.е. с задержкой от 0 до 15.625 мс при первом или однократном вызове Sleep и с задержкой, близкой к 15 мс при вызове Sleep в "пустом\холостом" цикле (за счет авто-синхронизации с сис. таймером). В итоге получается, что при вызове в холостом цикле Sleep(1) практически эквивалентна Sleep(15). Вот и прикинь загрузку процессора - несколько "жалких" сотен (или даже тысяч - роли не играет) тактов на вызов Sleep с переходом в ядро и ~15 мс*(частота_процессора) тактов чистого сна. Ес-но, что "Бесконечный цикл со Sleep(1) почти не грузит процессор"
          Цитата Jin X @
          Что там такого зашито внутри?

          ExpandedWrap disabled
            event = CreateEvent(NULL, FALSE, FALSE, NULL);
            //...
            void Sleep(DWORD timeot)
            {
               WaitForSingleObject(event, timeout);
            }


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

          Добавлено
          Цитата leo @
          В итоге получается, что при вызове в холостом цикле Sleep(1) практически эквивалентна Sleep(15).

          Я конечно не знаю как там в виндах реализовано, но я делал пробуждалку не только по таймеру.

          Добавлено
          Цитата Jin X @
          Как это можно реализовать кроме как через Sleep?

          А зачем оно надо?
          Сообщение отредактировано: shm -
            Цитата Славян @
            Уточните, что подразумевается под словом 'это'?
            Наоборот разгрузку. Мне нужно сделать цикл (spin-lock, в частности), который будут грузить проц минимально.
            Полагаю, что Sleep(1) - это не самый оптимальный способ сделать это.
              Вот ещё такой вариант нашёлся:
              Цитата \win2k\private\windows\media\avi\drawdib.16\ddt\ddt.c
              ExpandedWrap disabled
                void Sleep(UINT uSleep)
                {
                    MSG msg;
                    int id;
                 
                    id = SetTimer(NULL, 42, uSleep, NULL);
                 
                    while (GetMessage(&msg, NULL, 0, 0))
                    {
                        if (msg.message == WM_TIMER && msg.wParam == (WORD)id)
                            break;
                 
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                    }
                 
                    KillTimer(NULL, id);
                }
              Он выглядит несколько лучше, ибо всё приложение не "виснет" во время такой спячки, а хоть как-то реагирует.
                Ок. Чем же можно разгрузить проц на очень короткий срок (мкс, грубо говоря), кроме Sleep'а?

                Добавлено
                К сожалению, pause не разгружает проц вообще никак :(
                  Цитата Jin X @
                  К сожалению, pause не разгружает проц вообще никак

                  Разгружает, но не передает управление остальным потокам, так что как минимум стоит вставить еще и SwitchToThread. Загрузка проца в Винде имеет лишь посредственное отношение к фактической загрузке, а конкретно она высчитывается из фактического времени работы потока. Т. е. если в системе все потоки кроме твоего спят, а твой занят хоть чем-то кроме сна, то загрузка и будет 100%. Мне кажется в твоем случае стоит задуматься над событийной (асинхронной) моделью программы. Т. е. вместо твоего пустого цикла использовать WaitForSingleObject для ожидания результата чего-то. Тогда проблемы с пустой нагрузкой отпадут сами собой.

                  Добавлено
                  И да, если поток gui'шный, то можно использовать обработку сообщений потока через PostThreadMessage.
                  Сообщение отредактировано: shm -
                    Цитата shm @
                    Разгружает, но не передает управление остальным потокам, так что как минимум стоит вставить еще и SwitchToThread. Загрузка проца в Винде имеет лишь посредственное отношение к фактической загрузке, а конкретно она высчитывается из фактического времени работы потока. Т. е. если в системе все потоки кроме твоего спят, а твой занят хоть чем-то кроме сна, то загрузка и будет 100%. Мне кажется в твоем случае стоит задуматься над событийной (асинхронной) моделью программы. Т. е. вместо твоего пустого цикла использовать WaitForSingleObject для ожидания результата чего-то. Тогда проблемы с пустой нагрузкой отпадут сами собой.
                    А как я могу ждать обнуления 32-битной переменной через WaitForSingleObject?

                    Я запускал несколько потоков @: pause jmp @ и смотрел на температуру процессоров. Так вот, наличие pause никак не неё не влияет. Так что, у меня с разгрузкой всё-таки вопрос...

                    На данный момент решил сделать spin-loop-циклы вот так:

                    ( ( 265 spin-циклов, затем SwitchToThread ) * 4 раза, затем Sleep(1) ) * 4 раза.
                    Итого выходит 4096 циклов. Не так много, но и не мало.
                    После этого переходим на Sleep(1) после каждой проверки, максимально разгружая таким образом проц.

                    Готов обсудить цифры 256, 4, 4 на предмет оптимальности :)
                      Цитата shm @
                      Загрузка проца в Винде имеет лишь посредственное отношение к фактической загрузке
                      В продолжение темы: каким образом ядро делает так, что температура процессора остаётся низкой? А любой поток, делая даже pause в цикле будет нагревать его? На ум приходит только hlt, но...?
                        Цитата Jin X @
                        А как я могу ждать обнуления 32-битной переменной через WaitForSingleObject?

                        Явно никак. Но ты можешь в том месте, где ее устаналиаешь, добавить еще SetEvent. И все будет ОК.

                        Добавлено
                        Цитата Jin X @
                        Так вот, наличие pause никак не неё не влияет.

                        Довольно странно. Видимо в твоем процессоре такая реализация.
                        Цитата Jin X @
                        ( ( 265 spin-циклов, затем SwitchToThread ) * 4 раза, затем Sleep(1) ) * 4 раза.
                        Итого выходит 4096 циклов. Не так много, но и не мало.
                        После этого переходим на Sleep(1) после каждой проверки, максимально разгружая таким образом проц.

                        Криво и косо.
                        Цитата Jin X @
                        В продолжение темы: каким образом ядро делает так, что температура процессора остаётся низкой?

                        В системе есть System Idle потоки на каждое ядро. Они выполняют либо hlt, либо специальный aml код из acpi (и то и другое недоступно для user mode).
                          Цитата shm @
                          Довольно странно. Видимо в твоем процессоре такая реализация.
                          Я проверил это на 2-х процессорах: у меня на i5 (декстоп), на другом i5 (ноутбук) (позже ещё на i3 проверю, на другом ноуте). Результат один. Я даже больше скажу: с pause чуть больше греет :)

                          Цитата shm @
                          Криво и косо.
                          В чём кривизна? Как тогда не криво и не косо сделать?
                          Сделать через ивенты? (Но по любому же первые N (например, 4096) циклов надо будет оставить) :whistle:
                            Цитата Jin X @
                            Я даже больше скажу: с pause чуть больше греет

                            Будет время - я у себя протестирую.
                            Цитата Jin X @
                            В чём кривизна?

                            В том, что ты вместо использования готовых средств синхронизации занимаешься их эмуляцией.
                            Цитата Jin X @
                            (Но по любому же первые N (например, 4096) циклов надо будет оставить)

                            ExpandedWrap disabled
                              if N < 4094 then
                              ...
                              else
                                 WaitFor...
                              Цитата shm @
                              В том, что ты вместо использования готовых средств синхронизации занимаешься их эмуляцией.
                              Изначально была идея просто сделать spin-lock, но с экономией ресурсов, если процесс затянется. С использованием 1 простой переменной типа DWord или Int64, без Initialize и Delete. Т.е. наиболее быстрый и с наименьшими заморочками.

                              Сдаётся мне, что установка/ожидание event'а процесс тяжёлый... Хотя, могу ошибаться.
                                Я что скажу: если у тебя spin-локи грузят проц, то значит нужны эвенты или иные средства синхронизации (ибо цикл синхронизации отнюдь не маленький), которые могут усыпить поток. Во всяком случае что это процесс не тяжелее, чем sleep.
                                Сообщение отредактировано: shm -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) [1] 2 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0470 ]   [ 17 queries used ]   [ Generated: 28.03.24, 17:31 GMT ]