Удваиваются ли значения быстрее, чем значения с плавающей точкой в C #?

StackOverflow https://stackoverflow.com/questions/158889

Вопрос

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

Это было полезно?

Решение

Короткий ответ таков: "используйте ту точность, которая требуется для получения приемлемых результатов".

Ваша единственная гарантия заключается в том, что операции, выполняемые с данными с плавающей запятой, выполняются по крайней мере в элементе выражения с наивысшей точностью.Итак , умножение двух плаватьэто делается, по крайней мере, с точностью плавать, и умножение a плавать и еще двойной это было бы сделано по крайней мере с двойной точностью.Стандарт гласит, что "операции с [плавающей запятой] могут выполняться с более высокой точностью, чем тип результата операции".

Учитывая, что JIT для .NET пытается оставить ваши операции с плавающей запятой с требуемой точностью, мы можем взглянуть на документацию Intel для ускорения наших операций.На платформе Intel ваши операции с плавающей запятой могут выполняться с промежуточной точностью в 80 бит и преобразовываться до требуемой точности.

Из руководства Intel по операциям с плавающей запятой на C ++1 (к сожалению, у меня только мертвое дерево), они упоминают:

  • Используйте одинарный тип точности (например, float), если только не требуется дополнительная точность, получаемая с помощью double или long double.Типы с большей точностью увеличивают объем памяти и требования к пропускной способности....
  • Избегайте арифметических выражений смешанного типа данных

Этот последний момент важен, поскольку вы можете замедлить работу с помощью ненужных приведений к / от float и double, что приводит к JIT'd коду, который запрашивает x87 отказаться от своего 80-битного промежуточного формата между операциями!

1.Да, там написано C ++, но стандарт C # плюс знание среды CLR позволяют нам знать, что информация для C ++ должна быть применима в данном случае.

Другие советы

Я только что прочитал "Microsoft .NET Framework-Application Development Foundation 2nd" для экзамена MCTS 70-536, и на странице 4 (глава 1) есть примечание:

ПРИМЕЧАНИЕ. Оптимизация производительности с помощью встроенных типов
Среда выполнения оптимизирует производительность 32-разрядных целых типов (Int32 и UInt32), поэтому используйте эти типы для счетчиков и других часто используемых целых переменных.Для операций с плавающей запятой Double является наиболее эффективным типом, поскольку эти операции оптимизированы аппаратным обеспечением.

Ее написал Тони Нортроп.Я не знаю, является ли он авторитетом или нет, но я бы ожидал, что официальная книга для экзамена .NET должна иметь определенный вес.Это, конечно, не гарантия.Я просто подумал, что добавлю это к этому обсуждению.

Я задавал аналогичный вопрос несколько недель назад.Суть в том, что для оборудования x86 нет существенной разницы в производительности float по сравнению с double, если только у вас не возникнет проблема с памятью или вы не столкнетесь с проблемой кэша.В этом случае поплавки, как правило, будут иметь преимущество, поскольку они меньше.

Современные процессоры Intel выполняют все операции с плавающей запятой в регистрах шириной 80 бит, поэтому фактическая скорость вычислений не должна варьироваться между числами с плавающей запятой и удвоениями.

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

Кто-то еще упомянул, что следует избегать преобразований между float и double и вычислений, использующих операнды обоих типов.Это хороший совет, и если вы используете какие-либо функции математической библиотеки, которые возвращают удвоения (например), то сохранение всего в виде удвоений будет быстрее.

Я пишу трассировщик лучей, и замена плавающих значений на двойные для моего класса цветов дает мне ускорение на 5%.Замена векторов с плавающей запятой на двойные - это еще на 5% быстрее!Довольно круто :)

Это с Core i7 920

В арифметике 387 FPU float выполняется быстрее, чем double, только для определенных длительных итеративных операций, таких как pow, log и т.д. (и только если компилятор соответствующим образом устанавливает управляющее слово FPU).

Однако при использовании упакованной арифметики SSE это имеет большое значение.

Matthijs,

Вы ошибаетесь.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

Это указывает на то, что плавающие значения немного быстрее, чем двойные: http://www.herongyang.com/cs_b/performance.html

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

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

Я всегда думал, что процессоры были оптимизированы или одинаковы, независимо от float или double.Поиск оптимизаций в моих интенсивных вычислениях (множество извлечений из матрицы, сравнение двух значений) Я обнаружил, что значения с плавающей точкой выполняются примерно на 13% быстрее.

Это удивило меня, но я думаю, это связано с характером моей проблемы.Я не выполняю приведения между значениями float и double в основе операций, и мои вычисления в основном состоят из сложения, умножения и вычитания.

Это на моем i7 920, работающем под управлением 64-разрядной операционной системы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top