Is it possible to micro-optimize "x = max (a, b), y = min (a, b);"?

I had an algorithm that started as

int sumLargest2 ( int * arr, size_t n )
{
    int largest(max(arr[0], arr[1])), secondLargest(min(arr[0],arr[1])); 
    // ... 

and I realized that the first is probably not optimal, because the call max, and then minrepeated, if you think that the information necessary to reduce the minimum already exists as soon as you find the maximum. So I realized that I can do

   int largest = max(arr[0], arr[1]);
   int secondLargest = arr[0] == largest ? arr[1] : arr[0];

to hide useless handling min, but I'm not sure if it actually saves any number of operations. Are there any weird bit-shifting algorithms that can do the equivalent

int largest(max(arr[0], arr[1])), secondLargest(min(arr[0],arr[1]));

?????

+4
source share
8 answers

++ std::minmax std::pair . std::tie:

#include <algorithm>
#include <utility>

int largest, secondLargest;
std::tie(secondLargest, largest) = std::minmax(arr[0], arr[1]);

GCC, , minmax , C .

C :

int largest, secondLargest;
if (arr[0] < arr[1]) {
  largest = arr[1];
  secondLargest = arr[0];
} else {
  largest = arr[0];
  secondLargest = arr[1];
}
+10

:

int largestIndex = arr[1] > arr[0];
int largest = arr[largestIndex];
int secondLargest = arr[1 - largestIndex];

1 true 0 false.

+4

, min mad max, std::minmax_element. ++ 11.

auto result = std::minmax_element(arr, arr+n);
std::cout<< "min:"<< *result.first<<"\n";
std::cout<< "max :" <<*result.second << "\n";
+4

, ... , .

, std::partial_sort(). .

int sumLargest2(int * arr, size_t n) {
    int * first  = arr;
    int * middle = arr + 2;
    int * last   = arr + n;

    std::partial_sort(first, middle, last, std::greater<int>());

    return arr[0] + arr[1];
}

arr, std::partial_sort_copy().

+4
x = max(a, b);
y = a + b - x;

, .

.

+4

, :

if(a > b)
{
    largest = a;
    second = b;
}
else
{
     largest = b;
     second = a;
}

, , .

+3

?

#include <utility>

template<typename T>
    std::pair<T, T>
        minmax(T const& a, T const& b)
        { return b < a ? std::make_pair(b, a) : std::make_pair(a, b); }

//main
std::pair<int, int> values = minmax(a[0], a[1]);
int largest       = values.second;
int secondLargest = values.first;
+2

++...

, std:: minmax .

. , , , . . , . , , .

, , .

2 , , - . : 2 min/max 1 a b. .

2 , 32- malloc, . , - .

F.ex, , AVX2. (. , , CPU!). : https://software.intel.com/sites/landingpage/IntrinsicsGuide/ .

, , :

  • _mm256_min_epi32
  • _mm256_max_epi32
  • _mm256_stream_load_si256

, , , __mm256 . : min/max 256- , , 32- min/max .

: ... . , .

2 , , , , . , limit, , , , .

, , , ... . ; , , . , inline, . aligned, .

, int* . , , const.

. , SSE, AVX2 ( ). , - .

Run in release mode, compile with optimization on "fast" and see what happens under the hood. If you do all this, you should see instructions vpmax...appearing in the inner loops, which means that the compiler makes excellent use of intrinsics.

I do not know what else you want to do in the loop ... if you use all these instructions, you have to press the memory speed on large arrays.

+2
source

Source: https://habr.com/ru/post/1589039/


All Articles