fabs и сравнение очень быстрые для операций с плавающей запятой IEEE (например, одно целочисленное быстрое в принципе).
Если компилятор не вкладывает обе операции, либо ткните его до тех пор, пока он не сделает это, либо найдите реализацию для вашей архитектуры и вставьте ее самостоятельно.
Вы можете получить что-то из того факта, что положительные числа с плавающей точкой IEEE идут в том же порядке, что и целые числа с одинаковыми битовыми комбинациями. То есть
f > g iff *(int*)&f > *(int*)&g
Так что после того, как вы подстроились, я думаю, что max для int без веток также будет работать для float (при условии, что они, конечно, одного размера). Вот объяснение, почему это работает здесь: http://www.cygnus -software.com /apers / comparingfloats / comparingfloats.htm . Но ваш компилятор уже знает все это, как и ваш процессор, поэтому он может не иметь никакого значения.
Нет более быстрого способа сделать это. Ваш алгоритм уже O (n), и вы не можете победить его, и все равно посмотрите на каждый образец.
Я полагаю, что в SIMD вашего процессора (то есть SSE2 на Intel) есть что-то, что могло бы помочь, обрабатывая больше данных за такт, чем ваш код. Но я не знаю что. Если и есть, то, скорее всего, будет в несколько раз быстрее.
Вероятно, вы могли бы распараллелить на многоядерном процессоре, тем более что вы все равно имеете дело с 40 независимыми потоками. Это будет в лучшем случае несколько факторов быстрее. «Просто» запустите соответствующее количество дополнительных потоков, разделите работу между ними и используйте самый легкий примитив, который вы можете указать, когда они все завершены (возможно, барьер потока). Я не совсем понимаю, планируете ли вы максимальный из всех 40 потоков или максимальный из каждого в отдельности, поэтому, возможно, вам на самом деле не нужно синхронизировать рабочие потоки, кроме как для гарантии того, что результаты доставлены на следующий этап без повреждения данных.
Вероятно, стоит взглянуть на разборку, чтобы увидеть, сколько компилятор развернул цикл. Попробуйте развернуть его еще немного, посмотрите, имеет ли это какое-то значение.
Еще одна вещь, о которой стоит подумать: сколько промахов в кеше вы получаете, и можно ли уменьшить число, предоставив кешу несколько подсказок, чтобы он мог загружать нужные страницы раньше времени. Но у меня нет опыта в этом, и я бы не надеялся. __builtin_prefetch - это магическое заклинание на gcc, и я думаю, что первый эксперимент будет что-то вроде «предварительной выборки начала следующего блока перед входом в цикл для этого блока».
Какой процент требуемой скорости вы сейчас используете? Или это случай "как можно быстрее"?