How fast can you make linear search?

前端 未结 20 1854
死守一世寂寞
死守一世寂寞 2020-12-23 21:46

I\'m looking to optimize this linear search:

static int
linear (const int *arr, int n, int key)
{
        int i = 0;
        while (i < n) {
                      


        
相关标签:
20条回答
  • 2020-12-23 22:06

    You can do it in parallel.

    If the list is small, maybe it won't be worth to split the search, but if have to process lots of searches, then you can definitively run them in parallel. That wouldn't reduce the latency of the operations, but would improve the throughput.

    0 讨论(0)
  • 2020-12-23 22:09

    In one of the comments you said the array length is 64.

    Well if you must do it linearly, you can do:

    int i = -1;
    do {
      if (arr[0] >= key){i = 0; break;}
      if (arr[1] >= key){i = 1; break;}
      ...
      if (arr[62] >= key){i = 62; break;}
      if (arr[63] >= key){i = 63; break;}
    } while(0);
    

    However, I seriously doubt if that is faster than this binary search: *

    int i = 0;
    if (key >= arr[i+32]) i += 32;
    if (key >= arr[i+16]) i += 16;
    if (key >= arr[i+ 8]) i +=  8;
    if (key >= arr[i+ 4]) i +=  4;
    if (key >= arr[i+ 2]) i +=  2;
    if (key >= arr[i+ 1]) i +=  1;
    

    *Thanks to Jon Bentley for that one.

    Added: since you said this table is prepared once for a large number of searches, and you want fast, you could allocate some space somewhere and generate machine code with the values hard-wired into it. It could either be linear or binary search. If binary, the machine code would look like what the compiler would generate from this:

    if (key < value32){
      if (key < value16){
        ...
      }
      else {
        ...
      }
    }
    else {
      if (key < value48){
        ...
      }
      else {
        ...
      }
    }
    

    Then you just copy that into a place where you can call it.

    OR you could print the code above, compile and link it on the fly into a dll, and load the dll.

    0 讨论(0)
  • 2020-12-23 22:10

    I know that this topic is old, but I could not keep myself from posting. My optimization for a sentinel linear search is:

    int sentinel_linear_search(int key, int *arr, int n)
    {
        int last_value, i;
    
        /* considering that n is the real size of the array */
        if (--n < 1)
            return -1;
    
        last_value = arr[n];
    
        /* set array last member as the key */
        arr[n] = key;
    
        i = 0;
        while (arr[i] != key)
            ++i;
    
        /* recover the real array last member */
        arr[n] = last_value;
    
        return (arr[i] == key) ? i : -1;
    }
    

    The sentinel search great improvement is that its iteration uses only one conditional branch (key) instead of two (index and key).

        while (arr[i] != key)
            ++i;
    
    0 讨论(0)
  • 2020-12-23 22:12

    You've received many suggestions for improvements, but you need to measure each optimization to see which is best given your hardware and compiler.

    As an example of this, in the first version of this response, I guessed that by 100-200 array elements, the slightly higher overhead of binary search should easily be paid for by far fewer probes into the array. However, in the comments below, Mark Probst reports that he sees linear search ahead up to about 500 entries on his hardware. This reinforces the need to measure when searching for the very best performance.

    Note: Edited following Mark's comments below on his measurements of linear versus binary search for reasonably small N.

    0 讨论(0)
  • 2020-12-23 22:17

    You could search for a larger element than an int at a time - platform specifically, this can be much faster or slower depending on how it handles the larger data read. For instance, on a 64-bit system, reading in the array 2 elements at a time and checking the hi/low elements seperately could run faster due to less I/O. Still, this is an O(n) variety sort no matter what.

    0 讨论(0)
  • 2020-12-23 22:19

    Since you can put known values after the last valid entry, add an extra element n+1 = max to make sure the loop doesn't go past the end of the array without having to test for i < n.

    static int
    linear (const int *arr, int n, int key)
    {
            assert(arr[n] >= key);
            int i = 0;
            while (arr[i] < key) {
                    ++i;
            }
            return i;
    }
    

    You could also try unrolling the loop, with the same sentinel value:

    static int
    linear (const int *arr, int n, int key)
    {
            assert(arr[n] >= key);
            int i = 0;
            while (true) {
                    if (arr [i++] >= key)
                            break;
                    if (arr [i++] >= key)
                            break;
                    if (arr [i++] >= key)
                            break;
                    if (arr [i++] >= key)
                            break;
            }
            return --i;
    }
    
    0 讨论(0)
提交回复
热议问题