-
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;
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;
QueryPerformanceFrequency(Frequency);
Showmessage('Тест 1 = ' + FloatToStr(Frequency));
QueryPerformanceFrequency(TimeParams.Frequency);
Showmessage('Тест 2 = ' + FloatToStr(TimeParams.Frequency));
Showmessage('Тест 3 = ' + FloatToStr(TimeClass.GetFrequency));
Showmessage('Тест 4 = ' + FloatToStr(TimeClass.GetFrequencyEx));
TimeClass.Free;
end.
-
Сижу и удивляюсь. Никак понять не могу, что же не так?
-
Задача в любом случае уже решена. Пусть не как должно по идее быть реализована, но тем не менее всё работает. Просто мне бы хотелось узнать ну хоть какие-то версии от мастеров. На другой машине, Тест 3 = 2748115
-
Пройди пошаговую отладку. Что лежит в переменной, которую ты получаешь, на каждом шаге. Когда и откуда там ноль появляется? И еще: модификатор packed лучше убрать.
-
Не вижу причин убирать явным образом заданный модификатор packed так как оперирую структурами данных равными и превышающими размер SizeOf(Pointer). Хотя попробовал и без него, результат тот же. А по поводу пошаговой отладки: "от перемены мест слагаемых сумма не меняется". Ноль появляется вот тут:
QueryPerformanceFrequency(FTimeParams.Frequency);
Тем не менее спасибо за совет.
-
А если поставить после каждого вызова QueryPerformanceFrequency проверку GetLastError? И еще: сколько ядер на процессоре?
-
Дело говоришь! У самого как-то мозг не дошел до такой кондиции. Молодец. Процессор AMD Athlon II X4 630 (AM3, L2 2048Kb) Сделал вот так:
Showmessage(IntToStr(GetLastError));
QueryPerformanceFrequency(FTimeParams.Frequency);
Showmessage(IntToStr(GetLastError));
Showmessage(IntToStr(FTimeParams.Frequency));
Получил в сообщениях: {1} 0 {2} 998 {3} 0 Сделал вот так:
Showmessage(IntToStr(GetLastError));
QueryPerformanceFrequency(Temp);
Showmessage(IntToStr(GetLastError));
Showmessage(IntToStr(Temp));
Получил в сообщениях: {1} 0 {2} 87 {3} 2748115 Коды ошибок 998 - Invalid access to memory location (Неверная попытка доступа к адресу памяти) 87 -- Invalid parameter (Неверно задан параметр) Попробовал поменять для var Temp: Int64, на TLargeInteger, всё равно возвращает ошибку. а с ошибкой 998, мне вообще сложно разобраться. В чём же тут дело.
-
> [6] PavDimka (13.08.10 17:29) > а с ошибкой 998, мне вообще сложно разобраться. В чём же тут дело.
Обычно так ругаются на невыровненные данные
-
А как понять, выровнены они или нет из текста примера?
-
Меня лично смущает слово Packed в объявлении структуры "TTimeParams". Оно как раз имеет непосредственное отношение к "выравниванию".
-
> [8] PavDimka (13.08.10 23:50) > А как понять, выровнены они или нет из текста примера?
Например, на 32-битную границу, можно попробовать так: (ULONG_PTR(@MyVariable) and 3) = 0
-
> Германн © (14.08.10 02:01) [9] > Меня лично смущает слово Packed в объявлении структуры "TTimeParams". > Оно как раз имеет непосредственное отношение к "выравниванию". >
Я уже отвечал выше по тексту. > Хотя попробовал и без него, результат тот же.
-
1) packed нужно использовать только там, где это реально нужно. Здесь - нет. 2) На многоядерных атлонах были замечены глюки с QueryPerformanceCounter.
-
> miek (14.08.10 23:10) [12] > 1) packed нужно использовать только там, где это реально > нужно. Здесь - нет. >2) На многоядерных атлонах были замечены > глюки с QueryPerformanceCounter.
1) В реальной задаче в зависимости от выбранного алгоритма происходит большое число вызовов QueryPerformanceCounter. На выходе из алгоритма критически важным остается время выполнения четырех потоков, которое должно быть приближенным к целевым показателям. Если вдруг происходит отклонение от нормы, вся структура данных, а это порядка 20 счетчиков на одну итерацию алгоритма должна сохраниться в файл и отправиться на сервер. Время выполнения потоков одна минута, потом расчет по показателям. Количество итераций алгоритма за минуту, в пределах тысячи. Давайте обсудим, нужна ли директива Packed в данном случае? 2) Глюков с QueryPerformanceCounter замечено не было, но есть глюк с QueryPerformanceFrequency
-
> Давайте обсудим, нужна ли директива Packed в данном случае? В данном конкретном случае, она ни на что не влияет. Но, когда я что-то декларирую, предпочитаю ее использовать и на месте подгоняю, если что не так. 2. ты так и не сказал, что дала проверка на выравнивание ? Пример: TMyClass = class private FirstField: BYTE; SecondField: Int64; Как ты думаешь Second Field будет выровнена ? А в твоем примере надо проверять "по месту", ибо только тебе известно где ты сбил выравнивание.
-
Если для тебя критично время выполнения, то QPF/QPC вообще не подходит никаким образом. Там идет переход в режим ядра и жрется много тактов. Для скорости используют GetTickCount, для точности (но тут уже надо делать поправку на конкретный процессор) - RDTSC. Упаковка ускорит твою программу чуть менее, чем никак.
-
> 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 для многопроцессорных систем, то лучше преслушаться его совета. А упаковка помогает мне понять, где данные плотно лежат, а где нет.
-
>Я так и не понял, как делать это с помощью (ULONG_PTR(@MyVariable) and 3) = 0 Никак. Человек путает С++ и Дельфи. Здесь только "packed" и "не packed".
>Если Билли рекомендует QueryPerformanceCounter для многопроцессорных систем, то Обходя разложенные на земле грабли, ты теряешь драгоценный опыт.
p.s. На моем проце все четыре теста дают один результат 3579545. Угадай, сколько у меня ядер?
-
:) Улыбнул.
-
>> [17] miek (16.08.10 17:49) >Я так и не понял, как делать это с помощью (ULONG_PTR(@MyVariable) and 3) = 0 >>Никак. Человек путает С++ и Дельфи. Здесь только "packed" и "не packed".
Очень сложно искать взаимопониание с людьми, не только не не знающими основы некого языка, но и основы самомго программирования как такогого.
-
Таки да, выравнивание (нужно на 8): http://bobmoore.mvps.org/Win32/w32tip75.htmХотя лично я c этой проблемой никогда не сталкивался. Возможно, выравнивание нужно только для многоядерных AMD, которые уже отметились глючностью QPC (в данном случае требование выравнивания - скорее глюк, т.к. оно не документировано).
-
Тема так и называется. Глюк с QueryPerformanceFrequency, только надо сразу было добавить на многоядерных AMD. Всем спасибо. Тема закрыта.
|