2015-07-31 3 views
5

Мне нужен оптимизированный алгоритм бинарного поиска в массиве отсортированных чисел. Я сделал это и обнаружил, что с помощью поплавка чисел магазина быстрее, чем при использовании целого числа, потому что в конце концов я должен вычислитьСравнить float array as int array

(frameNumber-this->frameNumber[imin])/(this->frameNumber[imax]-this->frameNumber[imin]) 

this->frameNumber[imin] является самым большим номер кадра меньше равно, что frameNumber и this->frameNumber[imax] является наименьшим один больше равнее что. Этот код предназначен для вычисления прогресса между этими двумя ключевыми кадрами. массив frameNumber является статическим. Мне нужно только разобраться. Но обращайтесь к нему много раз с бинарным поиском и приведенным выше кодом для расчета прогресса.

Преобразование из int в float проводило некоторые циклы. Тогда я обнаружил, что в asm есть много инструкций fpu. Я беспокоюсь, что они могут быть медленнее, чем целые.

Так что вот и вопрос. Можно ли преобразовать массив отсортированных чисел с плавающей запятой в int * и запустить на нем двоичный поиск?

Это означает, что:

void binary_search(float key,float* array,...) 
{ 
    int key_integer=*(int*)&key; 
    int* array_intege(int*)array; 
    binary_search_for_integers(key_integer,array_integer,...); 
} 

Или мой выше вывод неверны? (Такие, как литье междунар плавать не так costy или Comparision между плавающим точками такой же скоростью, как целые числа?

спасибо!

+2

Ваш вопрос непонятен, но прямой ответ: нет, вы не можете преобразовать такой массив. – Amit

+5

Обычно это не сработает - он будет интерпретировать биты каждого элемента как ints вместо float. Тем не менее, есть интересная причуда с плавающей точкой IEEE, которая сохраняет порядок, если они интерпретируются как целые числа одинаковой длины. Таким образом, ваш бинарный поиск мог бы работать, если 'sizeof (int) == sizeof (float)' на вашей системе, и ни одно из значений не является NaN. Но это не гарантируется стандартами C или C++. – rlbond

+1

Он также не работает для отрицательных чисел. – fangzhangmnm

ответ

4

Это кажется плохой идеей. Используя целое сравнение данных с плавающей точкой на самом деле приведет к правильно упорядоченному массиву поплавков, а @rlbond указует (см. http://www.h-schmidt.net/FloatConverter/IEEE754.html играть с двоичными представлениями поплавков.) Убедитесь, что sizeof(int32_t) == sizeof(float) перед использованием этого.

хак, как это на самом деле не нужен. float сравнение не намного дороже, чем int сравнение, на современном оборудовании. (Intel Haswell: ucomiss - 1 мкп, с пропускной способностью 1 на каждый цикл. Сравнение с операндом памяти - 2 раза, без микро-слияния. И он не может быть с макро-предохранителем, как cmp/jcc) Однако FP add/sub и FP mul имеют более высокие задержки, чем их целые эквиваленты, и меньшую пропускную способность. Кажется глупым преобразовать целый массив в float, поскольку вы пишете ему только потому, что хотите сделать некоторую математику FP с минимальными и максимальными значениями в конце.

Команда load-and-convert-int-to-float (x86 cvtsi2ss (односкатное однозначное целое число с целым числом 2)) примерно так же быстро и занимает такое же кодовое пространство, что и обычная нагрузка (movss).

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

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

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

+0

Nonono не минимальные и максимальные значения. Я изменил код из [link] (https://en.wikipedia.org/wiki/Binary_search_algorithm), а imin и imax - всего два итератора. 'this-> frameNumber [imin]' является самым большим числом кадров, менее равным, чем 'frameNumber' и 'this-> frameNumber [imax]' является наименьшим, большим, чем это. Этот код предназначен для вычисления прогресса между этими двумя ключевыми кадрами. Поэтому я буду использовать все это только как плавающие. Эти данные являются статическими. Мне нужно только сортировать и преобразовывать его, когда он загружается с жесткого диска. – fangzhangmnm