Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> что работает быстрее? оптимизация, и всё с ней связанное. 
:(
    Опции темы
Sleepy_PIP
Дата 27.11.2004, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



кстати я был не прав. в большинстве прямо компилирующихся языков под любой платформой sin(cos, tg, и так далее) будет превращаться в первую очередь в вызов библиотечной. ф., а та уже в свою очередь задействует сопроцессор. что явно больше времени доступа к массиву даже с предвычислением индекса. да.



--------------------
--
Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем
свободным ..."
PM MAIL ICQ   Вверх
Sleepy_PIP
Дата 27.11.2004, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



объясните пожалуста. почему деление путем вычитания быстрее натурального деления?
вот код:
Код

public void TestS()
 {
   long ll=45000;
   long ts = System.currentTimeMillis();
   for(int i=0;i<1000000;i++)
   {
     for (; ll > 1; )
     {
       ll -= 5000;
     }
   }
   long te = System.currentTimeMillis();    
   System.out.println("del by minus " + (te-ts) + " milliseconds");
   ts = System.currentTimeMillis();
   for(int i=0;i<1000000;i++)
   {
     ll/=5000;
   }
   te = System.currentTimeMillis();    
   System.out.println("del by del " + (te-ts) + " milliseconds");

 }


вот результат:
del by minus 16 milliseconds
del by del 62 milliseconds

все-ж - от чего так происходит?
само деление - уже не вызов метода - это оператор, который вполне может быть выполнен на сопроцессоре, как в прочем и приведение типа.
Однако как сказад DomesticCat - так оно и получается, деление путем вычитания быстрее
Спасибо!
PS: что еще интересно - результат в ll для ll/=5000; всегда будет 0. ...


Это сообщение отредактировал(а) Sleepy_PIP - 27.11.2004, 19:18


--------------------
--
Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем
свободным ..."
PM MAIL ICQ   Вверх
Domestic Cat
Дата 27.11.2004, 20:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

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



Цитата(Sleepy_PIP @ 27.11.2004, 10:04)
del by minus 16 milliseconds
del by del 62 milliseconds


Ну не настолько же быстрее smile
Просто у тебя ошибка: после первого прохода цикла
Код

for (; ll > 1; )
{
       ll -= 5000;
}


ll становится равным 0. Тогда все оставшиеся 999999 раз этот цикл пропускается. Во втором с,лучае ноль получается из-за того, что ты делишь 45000 на 5000 1000000 раз. После девятого деления ll становится равным 1, а 1/5000 дает 0, т.к. оба числа целые и выполняется целочисленное деление (остаток = 1, результат = 0) .
Я сделал так:

Код

public class Test1
{
public static void main(String [] args)
 {
   long ll=45000;
   long ts = System.currentTimeMillis();
   for(int i=0;i<1000000;i++)
   {
ll=45000;
     for (; ll > 1; )
     {
       ll -= 5000;
     }
   }
   long te = System.currentTimeMillis();
   System.out.println("del by minus " + (te-ts) + " milliseconds");
ts = System.currentTimeMillis();
   for(int i=0;i<1000000;i++)
   {
ll=45000;
     ll/=5000;
   }
   te = System.currentTimeMillis();
   System.out.println("del by del " + (te-ts) + " milliseconds");

 }
}


и получил:
Цитата
del by minus 330 milliseconds
del by del 320 milliseconds

то есть скорость приблизительно одинакова.


--------------------

PM   Вверх
Sleepy_PIP
Дата 27.11.2004, 20:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Спасибо. ошибку я проглядел smile.

а вот дельфевый код
Код

procedure TForm1.Button1Click(Sender: TObject);
var
i: longint;
ll: longint;
ds, de: TDateTime;
dd: double;
begin
    ll:=45000;
    ds:=now;
    for i:=0 to 1000000000 do
    begin
      ll:=45000;
      while ll>1 do
         ll:=ll-5000;
    end;
    de:=Now;
    ShowMessage(TimeToStr(ds-de));
    ds:=now;
    for i:=0 to 1000000000 do
    begin
         ll:=45000;
         dd:=ll/5000;
    end;
    de:=Now;
    ShowMessage(TimeToStr(ds-de));

end;



выполняется в более чем 10 раз быстрее для деления. Правда тут есть одна тонкость - результат деления засовывается в вещественную переменную ...

Это сообщение отредактировал(а) Sleepy_PIP - 27.11.2004, 20:27


--------------------
--
Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем
свободным ..."
PM MAIL ICQ   Вверх
Domestic Cat
Дата 27.11.2004, 20:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

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



Цитата(Sleepy_PIP @ 27.11.2004, 11:25)

выполняется в более чем 10 раз быстрее для деления. Правда тут есть одна тонкость - результат деления засовывается в вещественную переменную ...


Ну, Делфи я не знаю, так что сказать не могу ничего. Если изменить так в Java коде:

Код

ll=45000;
double d = ll/5000;


то замедление незначительное: 330 мс против 390 мс.



--------------------

PM   Вверх
Sleepy_PIP
Дата 27.11.2004, 20:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



сделал аналог дельфевому коду, с исправлением ошибок smile
Код

public void TestS()
 {
   long ll=45000;
   double dd;
   long ts = System.currentTimeMillis();
   for(int i=0;i<1000000;i++)
   {
     ll=45000;      
     for (; ll > 1; )
     {

       ll -= 5000;
     }
   }
   long te = System.currentTimeMillis();
   System.out.println("del by minus " + (te-ts) + " milliseconds");
   ts = System.currentTimeMillis();
   ll=45000;
   for(int i=0;i<1000000;i++)
   {
     ll=45000;
     dd=ll/5000;
   }
   te = System.currentTimeMillis();
   System.out.println("del by del " + (te-ts) + " milliseconds");

 }



но результаты все равно я не понимаю:
del by minus 47 milliseconds
del by del 93 milliseconds
правда тут может влиять ll=45000; в цикле. неужели из-а этого?
нет, не из-а этого.
закоментаринивание в цикле ll=45000;
дает все равно:

del by minus 47 milliseconds

del by del 94 milliseconds

учусь! и еще на долго ...






--------------------
--
Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем
свободным ..."
PM MAIL ICQ   Вверх
Domestic Cat
Дата 27.11.2004, 20:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

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



Ну деление-то остается делением, оно все-таки медленнее smile К тому же тут ты используешь (неявно) еще один оператор - конвертации лонга в дабл :
Код

dd = ll/5000;

эквивалентно:

dd = (double) (ll / 5000);


а конвертация - медленная штука.

Это сообщение отредактировал(а) Domestic Cat - 27.11.2004, 20:46


--------------------

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


Опытный
**


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

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



Цитата(Domestic @ 27.11.2004, 20:40)
Ну деление-то остается делением, оно все-таки медленнее smile

сории, я еще не освоил дизасм (или как там в яве?) - не мог-бы ты привести во что выражается в байткоде вычитание и деление? случаем не в вызовы методов?
Сильно похоже что jvm действительно не использует сопроцессор вообще ... только догадки ...

Добавлено @ 20:46
Цитата(Domestic @ 27.11.2004, 20:40)
Ну деление-то остается делением, оно все-таки медленнее smile К тому же тут ты используешь (неявно) еще один оператор - конвертации интежера в дабл :
Код

dd = ll/5000;

эквивалентно:

dd = (double) (ll / 5000);


а конвертация - медленная штука.

дело в том, что конвертацией так-же может заведовать сопроцессор ... но увы и ах, я так и не понимаю на чем теряется время ....


--------------------
--
Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем
свободным ..."
PM MAIL ICQ   Вверх
Domestic Cat
Дата 27.11.2004, 20:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

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



Цитата
дело в том, что конвертацией так-же может заведовать сопроцессор ... но увы и ах, я так и не понимаю на чем теряется время ....


конвертацией занимается JVM, опкод l2d (в данном случае)

Цитата
не мог-бы ты привести во что выражается в байткоде вычитание и деление?


опкоды lsub и ldiv (для лонгов).

Все это ни о чем не говорит, т.к. JVM всегда вызывает методы ОС, она не работает с процессором напрямую.

Это сообщение отредактировал(а) Domestic Cat - 27.11.2004, 20:51


--------------------

PM   Вверх
Sleepy_PIP
Дата 27.11.2004, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Domestic @ 27.11.2004, 20:50)
Цитата
дело в том, что конвертацией так-же может заведовать сопроцессор ... но увы и ах, я так и не понимаю на чем теряется время ....


конвертацией занимается JVM, опкод l2d (в данном случае)

Цитата
не мог-бы ты привести во что выражается в байткоде вычитание и деление?


опкоды lsub и ldiv (для лонгов).

Все это ни о чем не говорит, т.к. JVM всегда вызывает методы ОС, она не работает с процессором напрямую.

ааа. вот тыт понятно. Спасибо! а жаль между прочим! JVM все одно на всех платформах своя - могли-б и сопр. задействовать на прямую ...

Добавлено @ 20:59
Цитата(Sleepy_PIP @ 27.11.2004, 20:55)
Цитата(Domestic @ 27.11.2004, 20:50)
Цитата
дело в том, что конвертацией так-же может заведовать сопроцессор ... но увы и ах, я так и не понимаю на чем теряется время ....


конвертацией занимается JVM, опкод l2d (в данном случае)

Цитата
не мог-бы ты привести во что выражается в байткоде вычитание и деление?


опкоды lsub и ldiv (для лонгов).

Все это ни о чем не говорит, т.к. JVM всегда вызывает методы ОС, она не работает с процессором напрямую.

ааа. вот тыт понятно. Спасибо! а жаль между прочим! JVM все одно на всех платформах своя - могли-б и сопр. задействовать на прямую ...

хотя я не прав опять - хочется выжать все из конкретной системы - пиши на компилирующихся в системный код языках. и все проблеммы будут разрешены smile


--------------------
--
Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем
свободным ..."
PM MAIL ICQ   Вверх
Zandr
Дата 17.3.2005, 08:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 433
Регистрация: 16.7.2004
Где: Новосибирск

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



Ребята, зачем деление вычитанием? Причем просто вот так в цикле! smile
Вчера вечером вспомнил, что можно делить столбиком, и что битовые операции очень быстрые. В общем вот что получилось:
Код
    static int div( int a, int b) {
        if (b == 0) {
            throw new ArithmeticException( "divide by zero");
        }
        int r = 0, t = 1;
        boolean plus = (a ^ b) >= 0;

//        if (a < 0) {
// alternative to 'a = -a;' (but probably less efficient) is 
//            a = ~a;
//            a++;
//        }
        if (a < 0) a = -a;
        if (b < 0) b = -b;

        while ( a > b) {
            b <<= 1;
            t <<= 1;
        }

        while ( t > 0) {
            if (a >= b) {
                a -= b;
                r += t;
            }
            b >>= 1;
            t >>= 1;
        }
        return plus ? r : -r;
    }

Кому не лень, сравните сскорости с делением методом вычитания в случаях, когда
а) число делится на бОльшее (т.е. нуль в результате)
б) очень большое число делится на единицу, например.
в) что-нибудь на что-нибудь, когда ответ - первые единицы (1, 2, 3, ...)
Вот случай (б) должен оказаться показательным smile

Это сообщение отредактировал(а) Zandr - 17.3.2005, 08:37
PM MAIL   Вверх
Zandr
Дата 17.3.2005, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 433
Регистрация: 16.7.2004
Где: Новосибирск

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



Ой, жалко - то как...... Тута ошибочка есть неразрешимая почти...
может вылазить при |a| > 0x40000000. Эх.

Это сообщение отредактировал(а) Zandr - 18.3.2005, 07:52
PM MAIL   Вверх
NotGonnaGetUs
Дата 17.3.2005, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



прикольно, запустил тест "деление путём вычитания" c ключом -server (взят выше)

del by minus 31 milliseconds
del by del 0 milliseconds

без него, что-то порядка

del by minus 47 milliseconds
del by del 78 milliseconds

%)
Оптимизации это великолепно.


Хотя вполне возможно, это следствие оптимизации цикла, в режиме -server.

Так и есть.

Если заменить 5000, на рандомный делитель int by = r.nextInt(4000)+1000;
то обычное деление выигрывает в обычном и сервер моде.
Короче говоря то, что делить вычитанием быстрее - тоже заблуждение.
В случае -server / выигрывает в 2 раза, -client / выигрывает на 15-20% (1782 vs 1468 ms).

Это сообщение отредактировал(а) NotGonnaGetUs - 17.3.2005, 18:29
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




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


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

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