Конференция "WinAPI" » Глюк с QueryPerformanceFrequency
 
  • PavDimka (09.08.10 14:18) [0]

    program Project2;

    uses
     Windows, SysUtils, Dialogs;

    Type
     TTimeParams = Packed Record
       Frequency: Int64;
     End;

     TTimeClass = Class
     Strict private
       FTimeParams : TTimeParams;
     Public
       Function GetFrequency: Int64;
       Function GetFrequencyEx: Int64;
     End;

    var
     TimeClass: TTimeClass;
     TimeParams: TTimeParams;
     Frequency: Int64;

    { TTimeClass }

    function TTimeClass.GetFrequency: Int64;
    begin
     QueryPerformanceFrequency(FTimeParams.Frequency);
     Result := FTimeParams.Frequency;
    end;

    function TTimeClass.GetFrequencyEx: Int64;
    var
     Temp: Int64;
    begin
     QueryPerformanceFrequency(Temp);
     FTimeParams.Frequency:= Temp;
     Result := FTimeParams.Frequency;
    end;

    begin
     TimeClass := TTimeClass.Create;

     { 1 }
     QueryPerformanceFrequency(Frequency);
     Showmessage('Тест 1 = ' + FloatToStr(Frequency));
     { 2 }
     QueryPerformanceFrequency(TimeParams.Frequency);
     Showmessage('Тест 2 = ' + FloatToStr(TimeParams.Frequency));
     { 3 }
     Showmessage('Тест 3 = ' + FloatToStr(TimeClass.GetFrequency));
     { 4 }
     Showmessage('Тест 4 = ' + FloatToStr(TimeClass.GetFrequencyEx));

     TimeClass.Free;

     { Результаты процедуры вывода сообщений
     Тест 1 = 2748115
     Тест 2 = 2748115
     Тест 3 = 0
     Тест 4 = 2748115
     И непонятно с чем связан.
     RAD Studio 2010, Windows 7
     }


    end.

  • PavDimka (09.08.10 14:21) [1]
    Сижу и удивляюсь.
    Никак понять не могу, что же не так?
  • PavDimka (09.08.10 14:33) [2]
    Задача в любом случае уже решена. Пусть не как должно по идее быть реализована, но тем не менее всё работает.
    Просто мне бы хотелось узнать ну хоть какие-то версии от мастеров.
    На другой машине, Тест 3 = 2748115
  • miek (09.08.10 21:49) [3]
    Пройди пошаговую отладку. Что лежит в переменной, которую ты получаешь, на каждом шаге. Когда и откуда там ноль появляется? И еще: модификатор packed лучше убрать.
  • PavDimka (12.08.10 16:13) [4]
    Не вижу причин убирать явным образом заданный модификатор packed так как оперирую структурами данных равными и превышающими размер SizeOf(Pointer). Хотя попробовал и без него, результат тот же.

    А по поводу пошаговой отладки: "от перемены мест слагаемых сумма не меняется". Ноль появляется вот тут:

    QueryPerformanceFrequency(FTimeParams.Frequency);



    Тем не менее спасибо за совет.
  • miek (12.08.10 19:02) [5]
    А если поставить после каждого вызова QueryPerformanceFrequency проверку GetLastError? И еще: сколько ядер на процессоре?
  • PavDimka (13.08.10 17:29) [6]
    Дело говоришь! У самого как-то мозг не дошел до такой кондиции. Молодец.

    Процессор
    AMD Athlon II X4 630 (AM3, L2 2048Kb)

    Сделал вот так:

    {1}Showmessage(IntToStr(GetLastError));
    QueryPerformanceFrequency(FTimeParams.Frequency);
    {2}Showmessage(IntToStr(GetLastError));
    {3}Showmessage(IntToStr(FTimeParams.Frequency));



    Получил в сообщениях:
    {1} 0
    {2} 998
    {3} 0

    Сделал вот так:

    {1}Showmessage(IntToStr(GetLastError));
    QueryPerformanceFrequency(Temp);
    {2}Showmessage(IntToStr(GetLastError));
    {3}Showmessage(IntToStr(Temp));



    Получил в сообщениях:
    {1} 0
    {2} 87
    {3} 2748115

    Коды ошибок
    998 - Invalid access to memory location (Неверная попытка доступа к адресу памяти)
    87 -- Invalid parameter (Неверно задан параметр)

    Попробовал поменять для var Temp: Int64, на TLargeInteger, всё равно возвращает ошибку.
    а с ошибкой 998, мне вообще сложно разобраться. В чём же тут дело.
  • Riply © (13.08.10 20:05) [7]
    > [6] PavDimka   (13.08.10 17:29)
    > а с ошибкой 998, мне вообще сложно разобраться. В чём же тут дело.

    Обычно так ругаются на невыровненные данные
  • PavDimka (13.08.10 23:50) [8]
    А как понять, выровнены они или нет из текста примера?
  • Германн © (14.08.10 02:01) [9]
    Меня лично смущает слово Packed в объявлении структуры "TTimeParams". Оно как раз имеет непосредственное отношение к "выравниванию".
  • Riply © (14.08.10 10:22) [10]
    > [8] PavDimka   (13.08.10 23:50)
    > А как понять, выровнены они или нет из текста примера?

    Например, на 32-битную границу, можно попробовать так: (ULONG_PTR(@MyVariable) and 3) = 0
  • PavDimka (14.08.10 13:33) [11]

    > Германн ©   (14.08.10 02:01) [9]
    > Меня лично смущает слово Packed в объявлении структуры "TTimeParams".
    >  Оно как раз имеет непосредственное отношение к "выравниванию".
    >


    Я уже отвечал выше по тексту.
    > Хотя попробовал и без него, результат тот же.
  • miek (14.08.10 23:10) [12]
    1) packed нужно использовать только там, где это реально нужно. Здесь - нет.
    2) На многоядерных атлонах были замечены глюки с QueryPerformanceCounter.
  • PavDimka (15.08.10 02:42) [13]

    > miek   (14.08.10 23:10) [12]
    > 1) packed нужно использовать только там, где это реально
    > нужно. Здесь - нет.
    >2) На многоядерных атлонах были замечены
    > глюки с QueryPerformanceCounter.

    1) В реальной задаче в зависимости от выбранного алгоритма происходит большое число вызовов QueryPerformanceCounter. На выходе из алгоритма критически важным остается время выполнения четырех потоков, которое должно быть приближенным к целевым показателям. Если вдруг происходит отклонение от нормы, вся структура данных, а это порядка 20 счетчиков на одну итерацию алгоритма должна сохраниться в файл и отправиться на сервер. Время выполнения потоков одна минута, потом расчет по показателям. Количество итераций алгоритма за минуту, в пределах тысячи.
    Давайте обсудим, нужна ли директива Packed в данном случае?
    2) Глюков с QueryPerformanceCounter замечено не было, но есть глюк с QueryPerformanceFrequency
  • Riply © (15.08.10 05:46) [14]
    > Давайте обсудим, нужна ли директива Packed в данном случае?
    В данном конкретном случае, она ни на что не влияет.
    Но, когда я что-то декларирую, предпочитаю ее использовать и на месте подгоняю, если что не так.
    2. ты так и не сказал, что дала проверка на выравнивание ?
    Пример:
    TMyClass = class
    private
     FirstField: BYTE;
     SecondField: Int64;
    Как ты думаешь Second Field будет выровнена ?
    А в твоем примере надо проверять "по месту",
    ибо только тебе известно где ты сбил выравнивание.
  • miek (15.08.10 09:07) [15]
    Если для тебя критично время выполнения, то QPF/QPC вообще не подходит никаким образом. Там идет переход в режим ядра и жрется много тактов. Для скорости используют GetTickCount, для точности (но тут уже надо делать поправку на конкретный процессор) - RDTSC.
    Упаковка ускорит твою программу чуть менее, чем никак.
  • PavDimka (15.08.10 22:03) [16]

    > Riply ©   (15.08.10 05:46) [14]
    >  что дала проверка на выравнивание ?
    Я так и не понял, как делать это с помощью (ULONG_PTR(@MyVariable) and 3) = 0

    Если подходит

    var
    A : Pointer;
    ...
    A := @FTimeParams.Frequency;
    ...


    То нужные данные лежат от первого бита до SizeOf(Int64) - это первая переменная в упакованной записи, которая лежит в обычном классе, на у тебя в примере. FirstField занимает объем SizeOf(Pointer), SecondField начинается с первого значения ячейки памяти.


    > miek   (15.08.10 09:07) [15]

    Если Билли рекомендует QueryPerformanceCounter для многопроцессорных систем, то лучше преслушаться его совета. А упаковка помогает мне понять, где данные плотно лежат, а где нет.
  • miek (16.08.10 17:49) [17]
    >Я так и не понял, как делать это с помощью (ULONG_PTR(@MyVariable) and 3) = 0
    Никак. Человек путает С++ и Дельфи. Здесь только "packed" и "не packed".

    >Если Билли рекомендует QueryPerformanceCounter для многопроцессорных систем, то
    Обходя разложенные на земле грабли, ты теряешь драгоценный опыт.

    p.s. На моем проце все четыре теста дают один результат 3579545. Угадай, сколько у меня ядер?
  • PavDimka (16.08.10 18:12) [18]
    :) Улыбнул.
  • Riply © (17.08.10 00:47) [19]
    >> [17] miek   (16.08.10 17:49)
    >Я так и не понял, как делать это с помощью (ULONG_PTR(@MyVariable) and 3) = 0
    >>Никак. Человек путает С++ и Дельфи. Здесь только "packed" и "не packed".

    Очень сложно искать взаимопониание с людьми, не только не не знающими
    основы некого языка, но и основы самомго программирования как такогого.
  • Sapersky (20.08.10 13:06) [20]
    Таки да, выравнивание (нужно на 8):
    http://bobmoore.mvps.org/Win32/w32tip75.htm
    Хотя лично я c этой проблемой никогда не сталкивался. Возможно, выравнивание нужно только для многоядерных AMD, которые уже отметились глючностью QPC (в данном случае требование выравнивания - скорее глюк, т.к. оно не документировано).
  • PavDimka (21.08.10 12:30) [21]
    Тема так и называется. Глюк с QueryPerformanceFrequency, только надо сразу было добавить на многоядерных AMD.
    Всем спасибо. Тема закрыта.
 
Конференция "WinAPI" » Глюк с QueryPerformanceFrequency
Есть новые Нет новых   [134431   +11][b:0][p:0.002]