Содержание материала

 

Порядок обработки инструкций меняется по мере готовности данных и ресурсов. Ресурсы это регистры и конвейеры исполнения. Я не вполне уверен, но я думаю, что инструкции обслуживаются в порядке поступления из программы, за исключением, когда инструкция задерживается. В этой ситуации следующая готовая инструкция начинает обслуживаться. Задержанная инструкция продолжит выполняться, как только причина задержки исчезнет. Задержка может произойти по причине отсутствия ресурса или не готовности данных.

После того, как мы посмотрели, как обслуживаются инструкции в конвейерах P4, мы приступим к измерению. Оптимизатор измерения ищет наилучшую возможность для нашего полинома ArcSin. Он базируется на наиболее простом алгоритме оптимизации, это исчерпывающий поиск. Мы просто пробуем множество комбинаций параметров и запоминаем каждый набор параметров, который дает наилучший результат. A и C начинаются в интервалах [AStart; AEnd] и [CStart; CEnd], а размер шага AStepSize и CStepsize. Это делается с помощью двух вложенных циклов.

Code:

StartA    := 0;

StartC    := -1;

EndA      := 1;

EndC      := 1;

AStepSize := 1E-2;

CStepSize := 1E-3;

OptA      := 9999;

OptC      := 9999;

A         := StartA;

while A <= EndA do

begin

C := StartC;

while C <= EndC do

begin

   Inc(NoOfIterations);

   MaxAbsError := CalculateMaxAbsError(A,C, ArcSinArray);

   if MaxAbsError <= MinMaxAbsError then

   begin

     MinMaxAbsError := MaxAbsError;

     OptA := A;

     OptC := C;

   end;

   C := C + CStepSize;

end;

A := A + AStepSize;

end;

 

Функция CalculateMaxAbsError рассчитывает количество точек X на интервале [-1;1], который определяет интервал функции ArcSin .

Code:

TMainForm.CalculateMaxAbsError(A, C : Double; ArcSinArray : TArcSinArray) : Double;

var

X, Y, D, B, Yref, Error, AbsError, MaxAbsError : Double;

 

begin

B := 0;

D := 0;

MaxAbsError := 0;

X := -1;

repeat

   Yref := ArcSin (X);

   Y := ArcSinApproxFunction(X, A, B, C, D);

   Error := Yref-Y;

   AbsError := Abs(Error);

   MaxAbsError := Max(MaxAbsError, AbsError);

   X := X + XSTEPSIZE;

until(X > 1);

Result := MaxAbsError;

end;

 

 

в каждой точке мы рассчитываем ошибку, вычитая значение Y из нашей функции аппроксимации из ссылки значения Y, полученное из  Delphi RTL функции ArcSin. Ошибка может быть положительной или отрицательной, нас же интересует абсолютное значение. Мы помним, что наибольшее абсолютное значение ошибки получается из двух значений MaxAbsError и AbsError, назначая из MaxAbsError. MaxAbsError инициализируется нулем, и в первом вычисление принимает значение первой ошибки (если она больше нуля). MaxAbsError возвращает результат из функции, после окончания полного цикла. В функции оптимизатора, два значения A и C, которые дают наименьшую максимальную ошибку, запоминаются вместе с действительным значением MinMaxAbsError.

Все, что делается в оптимизаторе это возможность расчета максимально количества комбинаций. По этой причине мы должны оптимизировать оптимизатор ;-), и функцию расчета. В этом уроке наши цели немного отличаются, поскольку все, что мы хотим, это получение правильных измерений для функций, которые мы хотим оптимизировать. Это все равно означает, что код оптимизатора должен занимать как можно меньше тактов, так как используемые в функциях большая часть общего количества использованных тактов. Первая оптимизация оптимизатора, которую мы сделаем, состоит в том, что не надо рассчитывать ссылки функции снова и снова. При возврате, нам не важно, какие значения имели A и C. Сделаем ссылку один раз и запишем значение Yref в массив.

Следующей оптимизации подвержены строки, которые рассчитывают MaxAbsError.

Длинная версия

Yref := ArcSinArray[I];

Error := Yref-Y;

AbsError := Abs(Error);

Короткая версия

AbsError := Abs(ArcSinArray[I]-Y);

Это поможет, поскольку Delphi создает множество лишнего кода, при компиляции FP кода.

Длинная версия компилируется в следующее

Code:

Yref := ArcSinArray[I];

 

mov eax,[ebp-$14]

mov edx,[eax+ebx*8]

mov [ebp-$48],edx

mov edx,[eax+ebx*8+$04]

mov [ebp-$44],edx

 

Error := Yref-Y;

 

fld   qword ptr [ebp-$48]

fsub qword ptr [ebp-$30]

fstp  qword ptr [ebp-$50]

wait

 

AbsError := Abs(Error);

 

fld qword ptr [ebp-$50]

fabs

fstp qword ptr [ebp-$10]

wait

 

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить