Использует ли double быстрее, чем float?
двойные значения хранят более высокую точность и удваивают размер поплавка, но оптимизированы ли процессоры Intel для поплавков?
то есть двойные операции так же быстро или быстрее, чем операции с плавающей точкой для+, -, * и /?
изменяется ли ответ для 64-разрядных архитектур?
7 ответов:
нет ни одного "процессора intel", особенно с точки зрения того, какие операции оптимизированы по отношению к другим!, но большинство из них, на уровне процессора (в частности, в рамках FPU), таковы, что ответ на ваш вопрос:
двойные деятельности как раз как быстро или быстрее, чем операции с плавающей точкой для +, -, * и /?
"да" -- внутри процессора, за исключением разделения и sqrt которые несколько медленнее для
double, чемfloat. (Предполагая, что ваш компилятор использует SSE2 для скалярной математики FP, как и все компиляторы x86-64, и некоторые 32-разрядные компиляторы в зависимости от параметров. Legacy x87 не имеет разной ширины в регистрах, только в памяти (он преобразуется при загрузке / хранении), поэтому исторически даже sqrt и разделение были такими же медленными дляdouble).например, у Хасвелла есть
divsdпропускная способность одного на 8 до 14 циклов (зависит от данных), но adivss(скалярное один) пропускная способность один в 7 циклов. x87, такfdiv8 до 18 пропускную способность цикла. (Номера от https://agner.org/optimize/. задержка коррелирует с пропускной способностью для разделения, но выше, чем номера пропускной способности.)The
floatверсии многих библиотечных функций, таких какlogf(float)иsinf(float)также будет быстрее чемlog(double)иsin(double), потому что у них гораздо меньше бит точности, чтобы получить право. Они могут использовать полиномиальные приближения с меньшим количеством членов, чтобы получить полную точность дляfloatиdouble
, занимая в два раза больше памяти для каждого числа явно подразумевает большая нагрузка на кэш(Ы) и больше пропускной способности памяти чтобы заполнить и разлить эти строки кэша из / в ОЗУ; время, когда вы заботитесь о производительности операции с плавающей запятой, когда вы делаете много таких операций, поэтому соображения памяти и кэша имеют решающее значение.
@Ричард ответ указывает, что есть и другие способы выполнения операций FP (SSE / SSE2 инструкции; старый добрый MMX был только целыми числами), особенно подходит для простых операций с большим количеством данных ("SIMD", одна инструкция / несколько данных), где каждый регистр вектора может упаковать 4 поплавка одно-точности или только 2 двойн-точности одни, так этот эффект будет еще более заметным.
в конце концов, вы должны ориентироваться, но мой прогноз заключается в том, что для разумный (т. е. большой;-) тесты, вы найдете преимущество придерживаться с одной точностью (при условии, конечно, что вы не нужно дополнительные биты точности!-).
если все вычисления с плавающей запятой выполняются в пределах FPU, то, нет, нет никакой разницы между a
doubleрасчет иfloatвычисление, потому что операции с плавающей запятой фактически выполняются с точностью 80 бит в стеке FPU. Записи стека FPU округляются соответствующим образом для преобразования 80-битного формата с плавающей запятой вdoubleилиfloatформат с плавающей точкой. Переездsizeof(double)байты в / из ОЗУ противsizeof(float)байт-это единственная разница в скорости.Если, однако, у вас есть векторизуемое вычисление, то вы можете использовать расширения SSE для запуска четырех
floatрасчеты в то же время, как дваdoubleрасчетов. Поэтому разумное использование инструкций SSE и регистров XMM может обеспечить более высокую пропускную способность при вычислениях, которые используют толькоfloats.
еще один момент, который следует учитывать, если вы используете GPU (графическая карта). Я работаю с проектом, который является численно интенсивным, но нам не нужен персик, который предлагает double. Мы используем GPU Карты, чтобы ускорить обработку. CUDA GPU нужен специальный пакет для поддержки double, а объем локальной оперативной памяти на GPU довольно быстрый, но довольно скудный. В результате использование float также удваивает объем данных, которые мы можем хранить на
еще один момент-память. Поплавки возьмите вдвое меньше оперативной памяти, чем в два раза. Если вы имеете дело с очень большими наборами данных, это может быть очень важным фактором. Если с помощью double означает, что вы должны кэшировать на диск против чистого ОЗУ, ваша разница будет огромной.
Так что для приложения, с которым я работаю, разница довольно важна.
в экспериментах добавления 3.3 для 2000000000 раз, результаты:
Summation time in s: 2.82 summed value: 6.71089e+07 // float Summation time in s: 2.78585 summed value: 6.6e+09 // double Summation time in s: 2.76812 summed value: 6.6e+09 // long doubleтаким образом, double быстрее и по умолчанию в C и c++. Это более портативный и по умолчанию для всех функций библиотеки C и C++. ALOS double имеет значительно более высокую точность, чем float.
даже Страуструп рекомендует удвоить поплавок:
" точное значение одинарной, двойной и расширенной точности определяется реализацией. Выбор правильной точности для задачи там, где выбор имеет значение, требуется значительное понимание вычислений с плавающей запятой. Если у вас нет такого понимания, получите совет, потратьте время на обучение или используйте double и надейтесь на лучшее."
возможно, единственный случай, когда вы должны использовать float вместо double, - это 64-битное оборудование с современным gcc. Потому что float меньше; double-8 байт, а float-4 байта.
Я просто хочу добавить к уже существующим отличным ответам, что
__m256?семейство же-инструкция-несколько данных (SIMD) внутренние функции C++ работают на или4doubles параллельно (например_mm256_add_pd), или 8floats параллельно (например_mm256_add_ps).Я не уверен, что это может перевести на фактический ускорить, но представляется возможным обрабатывать 2x как много поплавков в инструкция при использовании SIMD.
единственный действительно полезный ответ: только вы можете сказать. Вы должны проверить свои сценарии. Небольшие изменения в инструкциях и шаблонах памяти могут оказать значительное влияние.
Это, безусловно, имеет значение, если вы используете аппаратное обеспечение типа FPU или SSE (бывший делает всю свою работу с 80-битной расширенной точностью, поэтому double будет ближе; позже Это изначально 32bit, т. е. float).
обновление: s/MMX/ SSE / как отмечено в другом ответе.
с плавающей запятой обычно является расширением своего процессора общего назначения. Поэтому скорость будет зависеть от используемой аппаратной платформы. Если платформа имеет поддержку с плавающей точкой, я буду удивлен, если есть какая-либо разница.
Comments