Этюды для начинающих: мрамор и штукатурка эффективности

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Olej пишет:

ЕвгенийП пишет:

Тот, что Вы привели на большинстве ардуин без доработки работать не будет.

Хороший вопрос...

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

Вопрос как раз у Вас

Olej пишет:
А с чего бы ему не работать?

С того, что int здесь 16-ти разрядный, а весь хак-приём (начиная с константы 0x5f3759df ) заточен на 32-разрядный int.

Судя по Вашим постам, у Вас хороший уровень знаний и, полагаю, Вы уже всё поняли и в проверке на железе не нуждаетесь? Ну, если я ошибся, то проверяйте, конечно.

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

 

Olej
Olej аватар
Offline
Зарегистрирован: 05.03.2018

ЕвгенийП пишет:

С того, что int здесь 16-ти разрядный, а весь хак-приём (начиная с константы 0x5f3759df ) заточен на 32-разрядный int.

Ну так поставьте там uint32_t. 

ЕвгенийП пишет:

полагаю, Вы уже всё поняли и в проверке на железе не нуждаетесь? Ну, если я ошибся, то проверяйте, конечно.

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

 

 
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Olej пишет:

Ну так поставьте там uint32_t. 

Вы решили поучить меня программировать? Как мило :)))

Боюсь, Вы не поняли моей просьбы.

Мне кажется, что Вы, как говорят, "сечёте тему", а потому я Вас прошу не постить непроверенных кодов. Это отлично делают и чайники, причём в огромных количествах, не отбирайте у них хлеб.

Они (новички) потом ведь что делают. Берут код, который постил спец, смело вставляют его в свой 1000+ строчный говнокод, криво сшитый из натыренных везде кусков, а потом вываливают все эти тысячи строк на форум с вопросм. "а чё это у меня цикл if не работает?".

Поэтому у меня просьба ко всем спецам, быть внимательнее и не постить непроверенных кусков, т.к. люди воспринимают их за истину в последней инстанции. Настолько буквально воспринимают, что когда им говоришь об ошибке - начинают спорить: "Не может быть! Это уважаемый человек писал!"

Отсюда и моя просьба: господа, уважаемые люди, давайте будем поответсвеннее, по крайней мере в моих темах.

Olej
Olej аватар
Offline
Зарегистрирован: 05.03.2018

ЕвгенийП пишет:
И, пожалуйста, старайтесь не выкладывать непроврененных кодов, здесь и так, к сожалению, ...

Резонно...

Поэтому выкладываю проверенный код (не имея под рукой живого Arduino проверил это в симуляторе https://www.tinkercad.com/):

float FastInvSqrt( float x ) {
  float xhalf = 0.5f * x;
  uint32_t i = *(uint32_t*)&x;    // представим биты float в виде целого числа
  i = 0x5f3759df - ( i >> 1 );    // какого черта здесь происходит ?
  x = *(float*)&i;
  x = x * ( 1.5f- ( xhalf * x * x ) );
  return x;
}

void setup() {
  Serial.begin( 9600 );           // устанавливаем последовательное соединение
}

void loop() {
  uint32_t i = 0;                 // переменная для накопления числа
  while( Serial.available() > 0 ) // пока есть доступные данные
    i = i * 10 + ( Serial.read() - '0' );
  if( i != 0 ) {
    Serial.print( i, DEC );
    Serial.print( " => " );
    float s = 1. / FastInvSqrt( (float)i );
    Serial.println( s, 2 );
  }
  delay( 1000 );
}

Результаты выполнения выглядят так:

1000000 => 1001.70
10000 => 100.16
121 => 11.01
4 => 2.00
9 => 3.00

P.S. Интерес здесь в том, что алгоритм этот - очень неожиданный. А по времени выполнения - практически мгновенный. И подтверждает утверждение, с которого началось обсуждение темы, что если тщательно покопаться с поиском алгоритма, то можно добиться эффективности несравнимой ни с какой оптимизацией кода.

vlad072
Offline
Зарегистрирован: 01.08.2017

Хочу задать вопрос в тему, ситуация следующая. В цикле проверяется набор условий, какие то простые, другие значительно "тяжелее", требующие существенного времени. Есть ли смысл приводить выражения вида:

if ( <простое_условие_1> && <сложное_условие_1> && <простое_условие_2> && <сложное_условие_2> ) {
  // действие
 }

к выражениям:

if ( <простое_условие_1> && <простое_условие_2> ) if (<сложное_условие_1>) if (<сложное_условие_2>) {
  // действие
 }

или хитрый компилятор и здесь на выход даст одинаковый код?

sadman41
Offline
Зарегистрирован: 19.10.2016

У компилятора есть параметры оптимизации. Если Вы ими не управляете, то логично предположить, что ручная "оптимизация", как минимум, ничего не испортит.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

vlad072 пишет:

Хочу задать вопрос в тему, ситуация следующая. В цикле проверяется набор условий, какие то простые, другие значительно "тяжелее", требующие существенного времени. Есть ли смысл приводить выражения вида:

if ( <простое_условие_1> && <сложное_условие_1> && <простое_условие_2> && <сложное_условие_2> ) {
  // действие
 }

к выражениям:

if ( <простое_условие_1> && <простое_условие_2> ) if (<сложное_условие_1>) if (<сложное_условие_2>) {
  // действие
 }

Нет.

Не нужно плодить лишних if'ов. Просто переставьте условия в одном if, чтобы сложные в конце были. Здесь работает "ленивая логика", как только попадётся false, дальнейшее вычисляться не будет.