Страница: 1 | 2 |
Вопрос: Сколько операций нужно для...
Добавлено: 24.04.05 19:07
Автор вопроса: Страшный Сон
Кто знает, сколько операций выполняет комп для вычисления функций sin, cos и т. п.?
Ответы
Всего ответов: 30
Номер ответа: 1
Автор ответа:
Morpheus
Вопросов: 224
Ответов: 3777
Web-сайт:
Профиль | | #1
Добавлено: 24.04.05 19:24
1) mov листок бумаги to стол
2) mov карандаш to руки
3) mov линейку to руки
4) mov транспортир to руки
5) draw треугольник on листе бумаги
6) unload линейку
7) unload транспортир
8) unload арандаш
9) mov калькулятор to руки
10) поделить нужный катет на гипотенузу
11) unload калькулятор
12) определить знак результата
13) return результ
итого: 13 опреаций ))))))))
Номер ответа: 2
Автор ответа:
Yura
ICQ: 34372249
Вопросов: 3
Ответов: 8
Профиль | | #2
Добавлено: 24.04.05 19:24
Дизасемдлируй программу(лучше под дос, тк там мусора поменьше) и посчитай.
Номер ответа: 3
Автор ответа:
Morpheus
Вопросов: 224
Ответов: 3777
Web-сайт:
Профиль | | #3
Добавлено: 24.04.05 19:30
а если серьёзно есть вот такие функции (Delphi+Asm), может пригодятся:
{ Tan := Sin(X) / Cos(X) }
asm
FLD X
FPTAN
FSTP ST(0) { FPTAN pushes 1.0 after result }
FWAIT
end;
function CoTan(const X: Extended): Extended;
{ CoTan := Cos(X) / Sin(X) = 1 / Tan(X) }
asm
FLD X
FPTAN
FDIVRP
FWAIT
end;
function Secant(const X: Extended): Extended;
{ Secant := 1 / Cos(X) }
asm
FLD X
FCOS
FLD1
FDIVRP
FWAIT
end;
function Cosecant(const X: Extended): Extended;
{ Cosecant := 1 / Sin(X) }
asm
FLD X
FSIN
FLD1
FDIVRP
FWAIT
end;
Номер ответа: 4
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #4
Добавлено: 24.04.05 21:49
Вот тебе с интелоовских мануалов описание. Сколько тактов не сказано (или я не нашёл), а сколько операций см. ниже.
8.3.7. Trigonometric Instructions
The following instructions perform four common trigonometric functions:
FSIN Sine
FCOS Cosine
FSINCOS Sine and cosine
FPTAN Tangent
FPATAN Arctangent
These instructions operate on the top one or two registers of the x87 FPU register stack and they return their results to the stack. The source operands for the FSIN, FCOS, FSINCOS, and
FPTAN instructions must be given in radians; the source operand for the FPATAN instruction is given in rectangular coordinate units.
The FSINCOS instruction returns both the sine and the cosine of a source operand value. It operates faster than executing the FSIN and FCOS instructions in succession.
The FPATAN instruction computes the arctangent of ST(1) divided by ST(0), returning a result in radians. It is useful for converting rectangular coordinates to polar coordinates.
FSIN Replace ST(0) with its sine.
Computes the sine of the source operand in register ST(0) and stores the result in ST(0). The source operand must be given in radians and must be within the range -2^63 to +2^63.
IF ST(0) < 2^63 THEN
C2 = 0;
ST(0) = sin(ST(0));
ELSE (* source operand out of range *)
C2 = 1;
FI:
[b]FCOS Replace ST(0) with its cosine.[/b]
[i]Computes the cosine of the source operand in register ST(0) and stores the result in ST(0). The source operand must be given in radians and must be within the range -2^63 to +2^63.[/i]
[code]
IF |ST(0)| < 2^63 THEN
C2 = 0;
ST(0) = cosine(ST(0));
ELSE (*source operand is out-of-range *)
C2 = 1;
FI;
FSINCOS Compute the sine and cosine of ST(0); replace ST(0) with the sine, and push the cosine onto the register stack.
Computes both the sine and the cosine of the source operand in register ST(0), stores the sine in ST(0), and pushes the cosine onto the top of the FPU register stack. (This instruction is faster than executing the FSIN and FCOS instructions in succession.)
The source operand must be given in radians and must be within the range -2^63 to +2^63
IF ST(0) < 2^63 THEN
C2 < 0;
TEMP = cosine(ST(0));
ST(0) = sine(ST(0));
TOP = TOP - 1;
ST(0) = TEMP;
ELSE (* source operand out of range *)
C2 = 1;
FI:
FPTAN Replace ST(0) with its tangent and push 1 onto the FPU stack.
Computes the tangent of the source operand in register ST(0), stores the result in ST(0), and pushes a 1.0 onto the FPU register stack. The source operand must be given in radians and must be less than ±2^63.
IF ST(0) < 2^63 THEN
C2 = 0;
ST(0) = tan(ST(0));
TOP = TOP - 1;
ST(0) = 1.0;
ELSE (*source operand is out-of-range *)
C2 = 1;
FI;
FPATAN Replace ST(1) with arctan(ST(1)/ST(0)) and pop the register stack.
Computes the arctangent of the source operand in register ST(1) divided by the source operand in register ST(0), stores the result in ST(1), and pops the FPU register stack. The result in register ST(0) has the same sign as the source operand ST(1) and a magnitude less than +р.
The FPATAN instruction returns the angle between the X axis and the line from the origin to the point (X,Y), where Y (the ordinate) is ST(1) and X (the abscissa) is ST(0). The angle depends on the sign of X and Y independently, not just on the sign of the ratio Y/X. This is because a point (.X,Y) is in the second quadrant, resulting in an angle between р/2 and р, while a point (X,.Y) is in the fourth quadrant, resulting in an angle between 0 and .р/2. A point (.X,.Y) is in the third quadrant, giving an angle between .р/2 and .р.
ST(1) < arctan(ST(1) / ST(0));
PopRegisterStack;
Номер ответа: 5
Автор ответа:
Morpheus
Вопросов: 224
Ответов: 3777
Web-сайт:
Профиль | | #5
Добавлено: 25.04.05 00:22
2CyRax
А по-моему количество тактов зависит от конкретной модели процессора.
Я просто где то читал давно давно, что разные процессоры выполняют одну и ту же операцию за разное количесво тактов
А вообще, имхо не нужно знать абсолютное значение количества операций, чтобы оптимизировать прогу на скорость, достаточно знать относительную скорость тех или иных процедур и функций, чтобы выбрать самую быструю.
Номер ответа: 6
Автор ответа:
Neco
ICQ: 247906854
Вопросов: 133
Ответов: 882
Web-сайт:
Профиль | | #6
Добавлено: 25.04.05 00:30
Имхо vb'шный вариант синуса может сильно отличаться по скорости от того же сишного, т.к. наверняка там вначале идут проверки на соот-е типов и преобразования.
Чтобы точно посчитать количество операций, я бы заюзал функции о использовании которых Рихтер писал (QueryPerfCounter&GetProcIOCounter, точнее надо в ApiView'ре смотреть). Они для замера времени, которое проц тратит на выполнение твоего процесса (или потока, не помню счас точно), но может он и такты где-нить считает.
А даже если и не считает, то можно это дело вычислить, высчитав время операции, для которой заведомо известно количество тактов и разделив на неё время выполнения синуса или косинуса.
Номер ответа: 7
Автор ответа:
Neco
ICQ: 247906854
Вопросов: 133
Ответов: 882
Web-сайт:
Профиль | | #7
Добавлено: 25.04.05 00:35
Согласен с Morpheus'ом.
Процы имеют разные наборы инструкций (слышал что AMD'шные особенно быстро работают с плавающими) и следовательно старые процы не могут делать за один такт то, что может новый и тогда наверное это как-то эмулируется и время увеличивается...
Номер ответа: 8
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #8
Добавлено: 25.04.05 01:36
Сопроцессор имеет 3 типа данных: 2 целочисленных, 3 дробных и BCD. Число загружается ы сопроцессор из памяти и после завершения расчётов возвращается в память обратно.
Из этого следует что при выполении одной операции выигрыша в скорости никак не будет. Будет разве что удобство работы с дробными числами через сопроцессор. Схематически выполение операции сопроцессора можно представить так:
1. Загрузить число из памяти
2. Выполнить операцию(ции)
3. Вернуть результат в память.
Как видно из схемы, из 3-х операций 2 работают с памятью. Соответственно прирост в скорости можно получить лишь если между пунктом 1 и 3 выполняется несколько вычислений.
т.к. наверняка там вначале идут проверки на соот-е типов и преобразования.
Во первых это верно только для типа Variant. Кто тебе мешает использовать вещественные типы данных.
А во вторых, я хоть немного и знаком с его структурой, но всё равно не берусь делать таких легкомысленных заключений. Тип Variant - это ни что иное как 16-байтный UNION, где первые 8 байт определяют как будут интерпретироваться вторые 8 байт. К примеру если у тебя в Variant'е лежит Double, то первые 8 байт содержат информацию что во вторых 8-ми байтах храняться данные в формате Double. Преобразований тут никаких делать не надо, просто указывай источником указатель на данные, хранящиеся во вторых 8-ми байтах. Время может отнимать только проверка служебной информации из первых 8-ми байт.
Про преобразование целых/дробных типов тоже не могу сказать однозначно, ведь в сопроцессор можно загружать и целые числа. Я думаю это зависит от конкретной ситуации.
Могу посоветовать только проверить на практике какой код генерирует компилятор. Дизассемблируй экзешник и смотри что там как.
Номер ответа: 9
Автор ответа:
Страшный Сон
Вопросов: 46
Ответов: 848
Профиль | | #9
Добавлено: 25.04.05 17:17
Может 3 целочисленных и 2 "дробных"?
Выходит, для вычисления синуса достаточно одной инструкции... А сколько в ней тактов - не ясно. Хотя я могу провести исследование... И безо всякого дисасма.
Номер ответа: 10
Автор ответа:
Morpheus
Вопросов: 224
Ответов: 3777
Web-сайт:
Профиль | | #10
Добавлено: 25.04.05 17:36
А как по мне дык если разговор идёт о целочисленных типах то проц всё вычисляет в Extended (ну это в делфи так называется) а все остальные типы придуманы просто чтобы сэкономить память.
Может я чё то не так понял, в киижке по Делфи так писалось
Номер ответа: 11
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #11
Добавлено: 25.04.05 18:16
Может 3 целочисленных и 2 "дробных"?
Может быть, сечас мануалов нет, но могу дома посмотреть. Во всяком случае грузятся целые из памяти длиной WORD/DWORD PTR, а дробные WORD/DWORD/QWORD PTR.
Хотя я могу провести исследование... И безо всякого дисасма.
Попробуй. Тем более что узнать количество тактов дизассемблер тебе никак не поможет
Номер ответа: 12
Автор ответа:
Страшный Сон
Вопросов: 46
Ответов: 848
Профиль | | #12
Добавлено: 25.04.05 18:16
Ни фига, для выполнения расчетов с целыми числами и с плавающей точкой используются совсем разные инструкции для проца.
Тут какая-то фигня вышла - по проведенному мной исследованию вычисление функции sin требует порядка 160-170 тактов камня. Многовато это по моему...
Номер ответа: 13
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #13
Добавлено: 25.04.05 18:18
проц всё вычисляет в Extended (ну это в делфи так называется) а все остальные типы придуманы просто чтобы сэкономить память.
Ошибочное мнение. Как раз сопроцессору не всё равно. Тип числа влияет на размер мантисы в регистре сопроцессора.
Номер ответа: 14
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #14
Добавлено: 25.04.05 18:22
Ни фига, для выполнения расчетов с целыми числами и с плавающей точкой используются совсем разные инструкции для проца.
На самом деле в начале инструкции идёт специальный код, определяющий принадлежность её к сопроцессору (Сейчас не вспомню, но по моему это 11011).
Номер ответа: 15
Автор ответа:
Morpheus
Вопросов: 224
Ответов: 3777
Web-сайт:
Профиль | | #15
Добавлено: 25.04.05 18:23
Страшный Сон
Согласен, просто я же уточнил что
>если разговор идёт о целочисленных типах
Кстати, а как думаете что будет, если создать матрицу 100x100, заполнить её как таблицу пифагора и при умножении одно-двузначных чисел брать знаечение оттуда?
по моему, если в проге используется куча операций перемножения, то выигрыш при вытаскивании из матрицы будет заметен по сравнению с обычным перемножением. тем более что матрицу можно и 1000 на 1000 забацать