Здравствуйте.
В своих программах (числодробилки) мне приходиться иногда ставить маркеры неинециализированлости значения переменных. Есть идея применять константы типа NaN, Inf для обозначения таких чисел т.к. их легко отслеживать при отладке/запуске приложения. Вопрос в том грозит ли это чем-то самому коду (быстродействию, переносимости и т.п.) и как корректно присваивать такие значения переменным (скажем без деления на ноль) т.к. в манах нашел только проверку этих констант.
Спасибо.
С какой стати это должно чем-то грозить? Использование пограничных значений float'ов может даже прибавить скорости, если позволит выкинуть проверки каких-то флагов и избавиться таким образом от ветвлений. Другое дело, если у вас вдруг будет isnanf вызываться в каком-нибудь внутреннем цикле (что теоретически может быть медленее проверки флага) - но в таком случае можно порекоммендовать только больше никогда не писать числодробилки.
Что касается переносимости, в math.h определены все нужные константы, в частности NAN и INFINITY, точно это посмотреть можно в стандартах. Люниксовый math.h отсылает напрямую к/*
* ISO C99 Standard: 7.12 Mathematics <math.h>
*/
>Здравствуйте.
>В своих программах (числодробилки) мне приходиться иногда ставить маркеры неинециализированлости значения переменных.
>Есть идея применять константы типа NaN, Inf для обозначения таких чисел
>т.к. их легко отслеживать при отладке/запускеА толку, НАН в дебугере светится как 0.0000, INF как 1.00000
>А толку, НАН в дебугере светится как 0.0000, INF как 1.00000Ну да, а 0xFF как 1, а 0 как 0xdeadbeef. Не пори чушь.
float a = NAN, b = INFINITY;
---
(gdb) print a
$1 = nan(0x400000)
(gdb) print b
$2 = inf
>[оверквотинг удален]
>
>Ну да, а 0xFF как 1, а 0 как 0xdeadbeef. Не пори
>чушь.
>
>float a = NAN, b = INFINITY;
>---
>(gdb) print a
>$1 = nan(0x400000)
>(gdb) print b
>$2 = infДокажи что это переменная "a", а не переполнение или не глюк (ядра, оперативки, проца, gdb )
А млин, и правда работает
Starting program: /tmp/a.out ;
main () at test.c:11
11 a = NAN; b = INFINITY;
(gdb) print a
$1 = 0
(gdb) print b
$2 = 0
(gdb) step
13 return 0;
(gdb) print b
$3 = inf
(gdb) print a
$4 = nan(0x400000)
(gdb) step
14 }
(gdb) step
0x00007f2804938b54 in __libc_start_main () from /lib64/libc.so.6
А в Netbeans сцука, именно 1.000 и 0.000 показывает.
>А в Netbeans сцука, именно 1.000 и 0.000 показывает.В нем вообще очень слабый отладчик С программ. Даже с сигналами работать не умеет.
>
>Докажи что это переменная "a", а не переполнение или не глюк (ядра,
>оперативки, проца, gdb )
>Это не важно, если всплыл маркер - значит с кодом проблема, надо отлаживать.
>Докажи что это переменная "a", а не переполнение или не глюк (ядра,
>оперативки, проца, gdb )Тяжелый случай.
>А в Netbeans сцука, именно 1.000 и 0.000 показывает.
На бейсике пиши.
>Вопрос в том грозит
>ли это чем-то самому коду (быстродействию, переносимости и т.п.)Использование float и double в коде ведет к существенному замедлению работы программы. И когда нужна скорость выполнение применять не следует.
P.S. да и вобше формат float бесполезный, всегда обходился без него. всего 6 значаших чисел, абсолютной точности нет , а 6 разрядов можно и через int обрабатывать .
>>Вопрос в том грозит
>>ли это чем-то самому коду (быстродействию, переносимости и т.п.)
>
>Использование float и double в коде ведет к существенному замедлению работы программы.
>И когда нужна скорость выполнение применять не следует.
>
> P.S. да и вобше формат float бесполезный, всегда обходился без него.
>всего 6 значаших чисел, абсолютной точности нет , а 6 разрядов
>можно и через int обрабатывать .Интересное ответвление: каков приюлизительно прирост производительности при переходе от float к int на AMD( Intell) x86_64? ведь надо покрывать проверку переполнения int, компенсирует ли?
См. ниже и не слушай идиотов.
>Использование float и double в коде ведет к существенному замедлению работы программы.
>И когда нужна скорость выполнение применять не следует.Вообще-то, наоборот. Вот простой alpha blend.
#include <stdio.h>
#include <stdlib.h>
#include <sys/limits.h>
#include <sys/types.h>#define SIZE 1024*1024
#define ITERS 512#if defined FLOAT
# define TYPE float
#elif defined DOUBLE
# define TYPE double
#elif defined SHORT
# define TYPE unsigned short
# define MAX USHRT_MAX
#elif defined INT
# define TYPE unsigned int
# define MAX UINT_MAX
#else
#error please define FLOAT, DOUBLE, SHORT or INT
#endifint main() {
int i,j;
srand(234234234);TYPE color1[SIZE];
TYPE color2[SIZE];
TYPE alpha[SIZE];
TYPE output[SIZE];for (i = 0; i < SIZE; ++i) {
#if defined(FLOAT) || defined(DOUBLE)
color1[i] = (float)rand()/(float)RAND_MAX;
color2[i] = (float)rand()/(float)RAND_MAX;
alpha[i] = (float)rand()/(float)RAND_MAX;
#else
color1[i] = MAX*(float)rand()/(float)RAND_MAX;
color2[i] = MAX*(float)rand()/(float)RAND_MAX;
alpha[i] = MAX*(float)rand()/(float)RAND_MAX;
#endif
}for (j = 0; j < ITERS; ++j)
for (i = 0; i < SIZE; ++i)
#if defined(FLOAT) || defined(DOUBLE)
output[i] = (color1[i]*alpha[i] + color2[i]*(1-alpha[i]));
#elif defined(INT)
output[i] = ((uint64_t)color1[i]*alpha[i] + (uint64_t)color2[i]*(MAX-alpha[i]))/MAX;
#else
output[i] = (color1[i]*alpha[i] + color2[i]*(MAX-alpha[i]))/MAX;
#endif#if defined(FLOAT) || defined(DOUBLE)
printf("blend(%.4f, %.4f, %.4f) = %.4f\n", color1[0], color2[0], alpha[0], output[0]);
#else
printf("blend(%.4f, %.4f, %.4f) = %.4f\n",
(float)color1[0]/(float)MAX,
(float)color2[0]/(float)MAX,
(float)alpha[0]/(float)MAX,
(float)output[0]/(float)MAX);
#endifreturn 0;
}Вот так оно работает на 64bit машине. Как видите float всех рвет. Не буду приводить результат на 32бин машине, ибо 64бит арифметика убивает там все вообще нахрен (а без нее будем терять точность).
% make test
cc -O2 test.c -DFLOAT -o float
cc -O2 test.c -DDOUBLE -o double
cc -O2 test.c -DSHORT -o short
cc -O2 test.c -DINT -o int
time ./float
blend(0.2036, 0.0478, 0.8507) = 0.1803
1,87 real 1,87 user 0,00 sys
time ./double
blend(0.2036, 0.0478, 0.8507) = 0.1803
3,74 real 3,68 user 0,02 sys
time ./short
blend(0.2036, 0.0478, 0.8507) = 0.1803
2,03 real 2,03 user 0,00 sys
time ./int
blend(0.2036, 0.0478, 0.8507) = 0.1803
2,20 real 2,15 user 0,03 sys> P.S. да и вобше формат float бесполезный, всегда обходился без него.
>всего 6 значаших чисел, абсолютной точности нет , а 6 разрядов
>можно и через int обрабатывать .Да и вообще, вы ламер, хотя бы из-за категоричности высказываний и из-за бреда с 6 значащими числами (что вы вообще в виду имели?). Для любой задачи почти всегда можно точно сказать, что лучше использовать - float, fixed point или свою реализацию с произвольной точностью.
>>Использование float и double в коде ведет к существенному замедлению работы программы.
>>И когда нужна скорость выполнение применять не следует.
>
>Вообще-то, наоборот. Вот простой alpha blend.Пример не корректный. при работе с int зачем то идет преобразование во float, если работаешь с int так и работай. Идет лишняя операция вот и падение производительности.
И потом тест длительностью 2 сек не о чем не говорит.
Вот сделай преобразование Фурье во float и int и прогони 10 мин звуковой информации вот там и увидишь реальную производительность.>Да и вообще, вы ламер, хотя бы из-за категоричности высказываний и из-за
>бреда с 6 значащими числами (что вы вообще в виду имели?).
>Для любой задачи почти всегда можно точно сказать, что лучше использовать
>- float, fixed point или свою реализацию с произвольной точностью.Читай внимательно стандарт IEEE 754. (Стандарты читать полезно)
Практически в любой задачи можно обойтись без float. Это просто нужно понимать задачу.P.S. хотя есть процессоры где поддержка стандарта float реализована аппаратно там применение обосновано.
> Пример не корректный.Более, чем корректный.
>при работе с int зачем то идет преобразование
>во float, если работаешь с int так и работай.Это называется fixed point, неуч. Числа только выводятся как float, чтобы результат одинаково выглядел.
>Идет лишняя операция вот и падение производительности.
Потеря в генерации и распечатке, когда blend выполняется в 512 раз больше? Не смеши.
>И потом тест длительностью 2 сек не о чем не говорит.
Бгыгы. Ну поменяй константы, ты же можешь. Вот с размером 1024 и миллионом итераций:
time ./float
blend(0.2036, 0.0478, 0.8507) = 0.1803
1,99 real 1,99 user 0,00 sys
time ./double
blend(0.2036, 0.0478, 0.8507) = 0.1803
2,02 real 2,02 user 0,00 sys
time ./short
blend(0.2036, 0.0478, 0.8507) = 0.1803
3,77 real 3,77 user 0,00 sys
time ./int
blend(0.2036, 0.0478, 0.8507) = 0.1803
3,71 real 3,71 user 0,00 sys
nice make test 11,66s user 0,05s system 92% cpu 12,644 totalИнты сливают еще больше.
> Вот сделай преобразование Фурье во float и int и прогони 10
>мин звуковой информации вот там и увидишь реальную производительность.Думаешь, не делал? Какие там вообще инты нахрен? Возьми fftw3 и посмотри как там сделано и почему, если не веришь.
> Практически в любой задачи можно обойтись без float. Это просто нужно
>понимать задачу.Ну разумеется, можно ведь написать свой класс на интах вместо FPU. Ты всегда так делаешь?
>P.S. хотя есть процессоры где поддержка стандарта float реализована аппаратно там применение
>обосновано.Да, всем понятно что ты слил. Понимаешь, весь мир считает floating point на, как ни странно, FPU, а не ищет как заменить его на более торнозные инты.
Еще немного:
В данном коде видна основная ошибка, человек мыслит как математик а не как программист,
если есть задание получать числа в диапазоне от 0.0000 до 0.9999 то нужно работать с float по другому представить нельзя.
а если идет хранение в int, то идет постоянное преобразование, это медленно.немного переработанный код:
int main(int argc, char * argv[])
{
srand(234234234);
for (i = 0; i < SIZE; ++i) {
color1[i] = rand()/(RAND_MAX/9999);
color2[i] = rand()/(RAND_MAX/9999);
alpha[i] = rand()/(RAND_MAX/9999);
}
for (j = 0; j < ITERS; ++j)
for (i = 0; i < SIZE; ++i)
output[i] = (color1[i]*alpha[i] + color2[i]*(10000-alpha[i]));printf("blend(%.4f, %.4f, %.4f) = %.4f\n",
(float)color1[0]/(float)10000,
(float)color2[0]/(float)10000,
(float)alpha[0]/(float)10000,
(float)output[0]/(float)10000);
return 0;
}и результаты на 32 бит машине.
c int
~/work/test/float :> time ./int
blend(0.7010, 0.8640, 0.9905) = 0.7025
2.80user 0.01system 0:02.84elapsed 98%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+4230minor)pagefaults 0swaps~/work/test/float :> time ./float
blend(0.7011, 0.8641, 0.9906) = 0.7026
2.95user 0.01system 0:03.03elapsed 97%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+4229minor)pagefaults 0swapsполучили немного лучший результат. но идет падением точности.
P.S. значения получились другие наверно машина 32 бит
>В данном коде видна основная ошибка, человек мыслит как математик а
>не как программистНичего подобного.
>если есть задание получать числа в диапазоне от 0.0000 до 0.9999 то
>нужно работать с float по другому представить нельзя.Ой, как же так, float ведь не нужен?
>а если идет хранение в int, то идет постоянное преобразование, это медленно.
Еще раз - где там преобразования? Если ты про из float и в начале и во float в конце, я уже сказал что это бред. Где еще?
>получили немного лучший результат. но идет падением точности.
Что за машина? Когда-то FPU вообще был отдельно от процессора, вот там float'ы действительно были медленнее. У тебя такой?
Я тестирую на core2duo, и 32 бита и 64. Вот тебе float, double и int на 32 битах, SIZE=1024, ITERS=1024*1024, чтобы тестировать числодробилку, а не память. Для int MAX=65535, чтобы не было вообще никаких преобразований, int64_t соответственно убран.time ./float
blend(0.2036, 0.0478, 0.8507) = 0.1803
1.37 real 1.37 user 0.00 sys
time ./double
blend(0.2036, 0.0478, 0.8507) = 0.1803
1.38 real 1.38 user 0.00 sys
time ./int
blend(0.2036, 0.0478, 0.8507) = 0.1803
2.03 real 2.02 user 0.00 sysДальше спорить будешь?