Я пишу приложение, которое читает большие массивы поплавков и выполняет с ними простые операции. Я использую поплавки, потому что я думал, что это будет быстрее, чем удваивается, но после некоторых исследований я обнаружил, что есть некоторая путаница в этой теме. Может ли кто-нибудь уточнить это?
Является ли удвоение быстрее, чем плавает на С#?
Ответ 1
Короткий ответ: "используйте любую точность, необходимую для приемлемых результатов".
Ваша гарантия заключается в том, что операции, выполняемые с данными с плавающей запятой, выполняются, по меньшей мере, с наивысшим значением точности выражения. Таким образом, умножение двух float выполняется с по крайней мере точностью float, и умножение float и double будет по крайней мере, с двойной точностью. В стандарте указано, что операции [с плавающей запятой] могут выполняться с большей точностью, чем тип результата операции.
Учитывая, что JIT для .NET пытается оставить ваши операции с плавающей запятой в запрошенной точности, мы можем взглянуть на документацию от Intel для ускорения наших операций. На платформе Intel ваши операции с плавающей запятой могут выполняться с промежуточной точностью 80 бит и конвертировать до требуемой точности.
От руководства Intel к операциям с плавающей запятой С++ 1 (извините только мертвое дерево), они упоминают:
- Используйте один тип точности (например, float), если не требуется дополнительная точность, полученная двойным или длинным двойным. Более высокие типы точности увеличивают размер памяти и требования к пропускной способности....
- Избегайте смешанных арифметических выражений типа данных
Эта последняя точка важна как вы можете замедлить работу с ненужными нажатиями в/из float и double, что приводит к JIT'd код, который запрашивает x87, чтобы отбросить его 80-битный промежуточный формат между операциями!
1. Да, это говорит С++, но стандарт С# плюс знание CLR позволяет нам знать, что информация для С++ должна быть применима в этом случае.
Ответ 2
Я сделал аналогичный вопрос несколько недель назад. Суть в том, что для аппаратного обеспечения x86 нет существенной разницы в производительности поплавков против удвоений, если вы не стали привязаны к памяти, или вы начинаете работать в кеш-памяти. В этом случае поплавки обычно имеют преимущество, потому что они меньше.
Текущие процессоры Intel выполняют все операции с плавающей запятой в регистре с шириной 80 бит, поэтому фактическая скорость вычислений не должна варьироваться между поплавками и удвоениями.
Ответ 3
Я только что прочитал "Фонд разработки приложений Microsoft.NET Framework 2" для экзамена MCTS 70-536 и есть примечание на стр. 4 (глава 1):
ПРИМЕЧАНИЕ. Оптимизация производительности со встроенными типами
Время выполнения оптимизирует производительность 32-разрядных целых типов (Int32 и UInt32), поэтому используйте эти типы для счетчиков и других часто доступных интегральных переменных. Для операций с плавающей запятой Double является наиболее эффективным типом, потому что эти операции оптимизированы с помощью аппаратного обеспечения.
Это написано Тони Нортруп. Я не знаю, является ли он авторитетом или нет, но я бы ожидал, что официальная книга для .NET-экзамена должна иметь некоторый вес. Это, конечно, не gaurantee. Я просто подумал, что добавлю это к этой дискуссии.
Ответ 4
Если операции загрузки и хранения являются узким местом, то поплавки будут быстрее, потому что они меньше. Если вы выполняете значительное количество вычислений между нагрузками и магазинами, это должно быть примерно одинаковым.
Кто-то сказал об избежании конверсий между float и double и вычислениях, в которых используются операнды обоих типов. Это хороший совет, и если вы используете какие-либо функции математической библиотеки, которые возвращают удвоение (например), то сохраняя все, поскольку удваивается будет быстрее.
Ответ 5
Я пишу трассировщик лучей, и заменяя поплавки на двойники для моего класса Color, мне дают 5% ускорение. Замена векторов поплавками на удвоение еще на 5% быстрее! Довольно круто:)
Что с Core i7 920
Ответ 6
С 387 FPU арифметикой float работает только быстрее, чем двойной, для некоторых длительных итеративных операций, таких как pow, log и т.д. (и только если компилятор правильно устанавливает управляющее слово FPU).
С упакованной арифметикой SSE это имеет большое значение, хотя.
Ответ 7
Вы ошибаетесь. 32-бит намного эффективнее, чем 16-разрядный - в современных процессорах... Возможно, не по памяти, а по эффективности 32-битный путь.
Вы действительно должны обновить своего профессора до чего-то более "обновленного".;)
В любом случае, чтобы ответить на вопрос; float и double имеют точно такую же производительность, по крайней мере, на моем Intel i7 870 (как в теории).
Вот мои измерения:
(Я сделал "алгоритм", который я повторил в течение 10 000 000 раз, а затем повторил это в течение 300 раз, и из этого я сделал средний.)
double
-----------------------------
1 core = 990 ms
4 cores = 340 ms
6 cores = 282 ms
8 cores = 250 ms
float
-----------------------------
1 core = 992 ms
4 cores = 340 ms
6 cores = 282 ms
8 cores = 250 ms
Ответ 8
Это означает, что поплавки немного быстрее, чем удваивается: http://www.herongyang.com/cs_b/performance.html
В общем, в любое время, когда вы сравниваете производительность, вы должны принимать во внимание любые особые случаи, например, для использования одного типа требуются дополнительные преобразования или массирование данных? Они складываются и могут утверждать общие эталонные тесты.
Ответ 9
Поплавки должны быть быстрее в 32-битной системе, но профилируйте код, чтобы убедиться, что вы оптимизируете правильную вещь.
Ответ 10
Я всегда думал, что процессоры были оптимизированы или одинаковы независимо от float или double. Поиск оптимизаций для моих интенсивных вычислений (много получается из матрицы, сравнение двух значений). Я обнаружил, что поплавки работают на 13% быстрее.
Это меня удивило, но я думаю, это связано с характером моей проблемы. Я не делаю броски между float и double в ядре операций, и мои вычисления в основном добавляют, умножают и вычитают.
Это на моем i7 920, работающем на 64-разрядной операционной системе.