Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Sin быстрее чем из math.h 
:(
    Опции темы
Staskot
Дата 4.2.2012, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



feodorv 
несколько вопросов по коду возникло) как я понял sin из стандартной библиотеки) а mysin ваши функции) а при выводе выдает что стандартный синус быстрее чем ваш синус) извиняюсь за глупые вопросы) просто хочу разобраться)
PM MAIL   Вверх
feodorv
Дата 4.2.2012, 16:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Staskot @  4.2.2012,  16:35 Найти цитируемый пост)
а при выводе выдает что стандартный синус быстрее чем ваш синус) 

Ага. См. мой предыдущий пост)))



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Staskot
Дата 4.2.2012, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Очень жаль) а если попробывать табличный синус) ну и написать что то вроде
Код

//// заголовочный файл
#pragma once
#define MAX_ANGLE 360
class GE_FastMath
{private:    static double mCosTable[MAX_ANGLE];
static double mSinTable[MAX_ANGLE];public:    
static void Initialize();    
static double Cos(int iAngle) 
{ return mCosTable[iAngle]; }    
static double Sin(int iAngle) 
{ return mSinTable[iAngle]; }};
// cpp-файл
#include "StdAfx.h"
#define _USE_MATH_DEFINES
#include <math.h>
#include "GE_FastMath.h"
double GE_FastMath::mCosTable[MAX_ANGLE];
double GE_FastMath::mSinTable[MAX_ANGLE];
void GE_FastMath::Initialize(void)
{    for(int i = 0; i<MAX_ANGLE; i++)   
 {        double lRadian = i * (M_PI / 180); 
       mCosTable[i] = cos(lRadian);       
 mSinTable[i] = sin(lRadian);    }}

PM MAIL   Вверх
Staskot
Дата 5.2.2012, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



ну что ? у кого какие мысли есть?
PM MAIL   Вверх
volatile
Дата 5.2.2012, 23:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



feodorv, спасибо за небольшое исследование.
я примерно так и думал.
А вообще эти задачки написать синус быстрее чем crt-шный идут с допотопных времен.
(учителя еще на турбо С 1.0 пишут, тут это не редкость наблюдать)

Так вот, в те времена, сопроцессор не  был встроен в ЦП, и под него была предусмотрена панелька, которая почти у всех пустовала.
Ну и этот сопроцессор эмулировали программно.
В те времена, когда и учились нынешние преподаватели  smile и была такая задачка, которая банально решалась уменьшением точности.
В наше время, со встроенным сопроцессором, задачка обогнать встроенный синус, превратилась в практически не решаемую. (ну по крайней мере совсем не для начинающих)


Цитата(Staskot @  5.2.2012,  16:02 Найти цитируемый пост)
ну что ? у кого какие мысли есть? 

Staskot, ну так замерьте, и опубликуйте здесь ваши результаты.
кто-ж это кроме вас сделает?

PM MAIL   Вверх
XLAT
Дата 6.2.2012, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 8.1.2012

Репутация: нет
Всего: нет



Все double замени на float
Вот и будет тебе потеря точности(4 байта вместо 8 на одно число) и лишний профит на компенсацию.

можно ещё ассемблерную вставку вставить с соответствующей настройкой CW - регистра управления FPU: 9 и 10 биты сброшены в нуль. Но это если препод разрешит, а, вообще то первого тебе будет достаточно.

PM MAIL   Вверх
Staskot
Дата 6.2.2012, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



вставки нельзя использовать) хоть там и хорошее ускорение будет) double менять на float тоже не вариант) меня заставляют работать только с даблой) вот мучаюсь с табличным синусом) может кто-то поможет мне дописать код?
PM MAIL   Вверх
borisbn
Дата 6.2.2012, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(Staskot @  6.2.2012,  12:30 Найти цитируемый пост)
может кто-то поможет мне дописать код?

так уже написан... вызываешь свои же ф-ции GE_FastMath::Sin и GE_FastMath.Cos
Код
double mysin( double x ) {
    GE_FastMath::Sin( (int)x );
}




--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Staskot
Дата 6.2.2012, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



я знаю как дописать чтобы точность была 10 знаков после запятой)
PM MAIL   Вверх
Staskot
Дата 6.2.2012, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



упс)) я НЕ знаю как сделать чтоб точность была именно 10 знаков
PM MAIL   Вверх
Staskot
Дата 6.2.2012, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Вообщем вот что я имею на данный момент)
Код

//// заголовочный файл
#pragma once
#define MAX_ANGLE 360
class GE_FastMath
{private:    static double mCosTable[MAX_ANGLE];
static double mSinTable[MAX_ANGLE];public:    
static void Initialize();    
static double Cos(int iAngle) 
{ return mCosTable[iAngle]; }    
static double Sin(int iAngle) 
{ return mSinTable[iAngle]; }};
// cpp-файл
#include <iostream>
#include <conio.h>
#include <math.h>
#include <windows.h>
#include "StdAfx.h"
#define _USE_MATH_DEFINES
#include <math.h>
#include "GE_FastMath.h"

const int N=100;
double GE_FastMath::mCosTable[MAX_ANGLE];
double GE_FastMath::mSinTable[MAX_ANGLE];
void GE_FastMath::Initialize(void)
{    for(int i = 0; i<MAX_ANGLE; i++)   
 {        double lRadian = i * (M_PI / 180); 
       mCosTable[i] = cos(lRadian);       
 mSinTable[i] = sin(lRadian);    }}
double mysin( double x ) {
    GE_FastMath::Sin( (int)x );
    return x;
}

void main(void)
{int i;
  double x1,x2,y,z;
x1=1.0; x2=2.0-1.0;
  y=(x2-x1)/N;
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);

LARGE_INTEGER time1;
QueryPerformanceCounter(&time1);
for(i=0,z=x1;i<N;i++,z+=y)
   {
      mysin(z);
 }
LARGE_INTEGER time2;
QueryPerformanceCounter(&time2);
time2.QuadPart -= time1.QuadPart;
double span = (double) time2.QuadPart / freq.QuadPart; 
printf( "for sin time: %f seconds\n", span );
getch();
}

Как я понял это кончательный вариант) вот что получилось для стандартного синуса 0.000022 секунды) а для mysin 0.000012) для меня этот результат хороший) но при больших N  происходит проигрывание mysin, причем ощутимое проигрывание) вообщем вопрос как сделать чтоб точность сохранялась 10 знаков ни больше ни меньше)
PM MAIL   Вверх
bsa
Дата 6.2.2012, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196




 ! 
bsa
Staskot, отформатируй код. Уважай собеседников!!!

PM   Вверх
borisbn
Дата 6.2.2012, 14:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(Staskot @  6.2.2012,  14:01 Найти цитируемый пост)
double mysin( double x ) {
    GE_FastMath::Sin( (int)x );
    return x;
}

неправильно. возвращать нужно не x, а
Код
return GE_FastMath::Sin( (int)x );

и ещё где-нибудь в начале main() нужно вызвать GE_FastMath::Initialize();
и ещё: 100 итераций для сравнения времени маловато. сделай 1 млн.

Добавлено через 1 минуту и 37 секунд
P.S. Выводи время в мс (просто умножь на 1e3) - читаеме ж будет


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Staskot
Дата 6.2.2012, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Цитата(borisbn @  6.2.2012,  14:44 Найти цитируемый пост)
и ещё где-нибудь в начале main() нужно вызвать GE_FastMath::Initialize();
и ещё: 100 итераций для сравнения времени маловато. сделай 1 млн.

Добавлено через 1 минуту и 37 секунд
P.S. Выводи время в мс (просто умножь на 1e3) - читаеме ж будет

Всё равно получается что стандартный синус быстрее чем мой) но это при больших итерациях) а прималеньких мой быстрее)
PM MAIL   Вверх
borisbn
Дата 6.2.2012, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



лови, экспериментируй...
Код

#include <iostream>
#include "TimeMeasure.h"
#include <math.h>

const int MAX_ANGLE = 3600;
const int N = 1000000;
const double Pi = acos( -1.0 );
double tableSin[ MAX_ANGLE ];

void initTableSin() {
    for ( int i = 0; i < MAX_ANGLE; i++ )
    {
        tableSin[ i ] = sin( i / (double)MAX_ANGLE * 360.0 * Pi / 180.0 );
    }
}

double mysin( double x ) {
    return tableSin[ (int)( x / 360.0 * MAX_ANGLE / Pi * 180.0 ) ];
}

double res_math[ N ];
double res_my[ N ];

int main() {
    initTableSin();
    
    double x0 = 0;
    double x1 = 2 * Pi;
    double z = ( x1 - x0 ) / (double)N;
    TimeMeasure math_sin;
    double x = x0;
    for ( int i = 0; i < N; i++, x += z )
    {
        res_math[ i ] = sin( x );
    }
    std::cout << "math::sin time is " << math_sin.elapsed_ms() << " ms" << std::endl;
    TimeMeasure my_sin;
    x = x0;
    for ( int i = 0; i < N; i++, x += z )
    {
        res_my[ i ] = mysin( x );
    }
    std::cout << "my::sin time is " << my_sin.elapsed_ms() << " ms" << std::endl;
    double delta = 0;
    for ( int i = 0; i < N; i++ ) {
        delta += fabs( res_my[ i ] - res_math[ i ] );
    }
    std::cout << "delta is " << delta / (double)N << std::endl;
}



файл TimeMeasure.h:
Код

#if !defined ( _TIMEMEASURE_H_INCLUDED_ )
#define _TIMEMEASURE_H_INCLUDED_

#include <windows.h>

/** \brief Классик для точного измерения времени выполнения чего-либо

    Интерфейс спи..ен с Qt, за исключением того, что в TimeMeasure::TimeMeasure сразу измеряется
    время начала выполнения этого чего-либо :)

    \br
    Пример использования 1:
\code
    TimeMeasure t;
    do_something();
    double msecs_of_something = t.elapsed_ms();
\endcode
    Пример использования 2:
\code
    TimeMeasure t;
    ...
    t.start();
    do_something();
    double mks_of_something = t.elapsed_mks();
\endcode
*/
class TimeMeasure
{
public:
    /** \brief Создание классика измерения
    
        В конструкторе измеряется время начала выполнения чего-либо.
        Его всегда можно измерить заново функцией TimeMeasure::start()
    */
    TimeMeasure()
    {
        QueryPerformanceFrequency( &m_frequency );
        start();
    }
    /// Измерить время начала выполнения чего-либо
    void start()
    {
        QueryPerformanceCounter( &m_startTicks );
    }
    /// Получить разницу времени от функции TimeMeasure::start() до текущего в секундах
    long long elapsed_ticks() const
    {   
        LARGE_INTEGER nowTicks;
        QueryPerformanceCounter( &nowTicks );
        return (nowTicks.QuadPart - m_startTicks.QuadPart);
    }
    /// Получить разницу времени от функции TimeMeasure::start() до текущего в секундах
    double elapsed_sec() const
    {   
        LARGE_INTEGER nowTicks;
        QueryPerformanceCounter( &nowTicks );
        return (nowTicks.QuadPart - m_startTicks.QuadPart) / (double)m_frequency.QuadPart;
    }
    /// Получить разницу времени от функции TimeMeasure::start() до текущего в миллисекундах
    double elapsed_ms() const
    {
        return elapsed_sec() * 1e3;
    }
    /// Получить разницу времени от функции TimeMeasure::start() до текущего в микросекундах
    double elapsed_mks() const
    {
        return elapsed_sec() * 1e6;
    }
private:
    LARGE_INTEGER m_startTicks; ///< Время начала в тиках
    LARGE_INTEGER m_frequency;  ///< Количество тиков в секунду
};
#endif // !defined ( _TIMEMEASURE_H_INCLUDED_ )



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Страницы: (4) Все 1 [2] 3 4 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0653 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.