how is the most significant bit radix sort more efficient than the least significant bit radix sort?

jsguy

I was just reading the following question: Radix sort most significant first or least significant, which is faster?

And the author of the accepted answer was suggesting that the MSD radix sort is indeed faster. I do not see why however.

I have implemented both LSD and MSD (binary based by doing shift operations), LSD is iterative, requires just one bucket array, while MSD is recursive and requires one individual bucket array per every recursion call.

If you create a random array of 10 million integers, I cannot see how MSD will be faster than LSD, since you will be allocating extra bucket arrays every time you re enter your function and also you will have to face the overhead of the recursion call themselves.

I can see how the combination of MSD and LSD can give an over all boost (run MSD for the first few bits and LSD for the rest of the bits to reduce cache misses), but how is MSD alone expected to be more efficient than LSD given its recursive nature and the fact that you need a new bucket array for every recursion call, unlike LSD which is both iterative and just requires one bucket array for the entire sorting procedure?

bcmpinc

Answer

The number of iterations in MSD radix depends on the input size, whereas the number of iterations in LSD radix sort depends on the key length. This often leads to MSD radix sort requiring significantly fewer iterations than LSD radix sort and is therefore faster.

Memory allocations are not an issue, as MSD radix sort can easily be implemented in-place.

Rationale

I've made an implementation for both LSD and MSD radix sort, so I could see what properties they have that makes MSD radix sort faster than LSD radix sort.

I've compared their speeds with std::sort on an array of 100.000.000 random positive 63-bit integers (I used std::sort's result I also used for verifying the sorted arrays) and got the following results:

  • Pure LSD sort : 10.5s
  • std::sort : 9.5s
  • Pure MSD sort : 9.3s
  • MSD sort + insertion_sort : 7.6s

So, it is slightly faster than std::sort, and if the leaves are sorted with insertion_sort, it is quite a bit faster.

Why might MSD radix sort be faster than LSD radix sort?

  • There is the cache-locality, though I doubt whether this is really important, as LSD radix sort also scans through the array, instead of performing random access.
  • MSD radix sort can be implemented such that its space complexity is O(d k), and thus only depends on the radix d and the length of the items k. This can be allocated on the stack, which is almost free. Hence it is basically an in-place sorting algorithm.
  • The bottom layers can be pruned. I.e. when a bucket contains only 1 element, it is already sorted and thus does not need to recurse on that bucket. Hence, MSD radix sort only needs to perform approximately log(n)/log(d) iterations. While LSD radix sort always must perform k iterations.

I believe that this last point is the reason why MSD radix sort is often faster than LSD radixsort. If the input data is uniformly random distributed, then the expected running time is O(n log(n)/log(d)), whereas LSD radix sort's running time is O(n k). And usually n is a lot smaller than k^d. Only if n = o(k^d), LSD radix sort would be faster. However, in that case counting sort (radix sort with k=1) can be used as well.

The implementations

inline void insertion_sort(int64_t * array, int n) {
  for (int i=1; i<n; i++) {
    int64_t val = array[i];
    int j = i;
    while (j>0 && array[j-1] > val) {
      array[j] = array[j-1];
      j--;
    }
    array[j] = val;
  }
}

void msd_sort(int64_t * array, int n, int64_t bit=60) {
  const int64_t mask = INT64_C(7);
  // Count bucket sizes
  int count[9]={};
  for (int i=0; i<n; i++) {
    count[((array[i]>>bit) & mask)+1]++;
  }
  // Create holes.
  int loc[8];
  int64_t unsorted[8];
  int live = 0;
  for (int i=0; i<8; i++) {
    loc[i] = count[i];
    count[i+1]+=count[i];
    unsorted[live] = array[loc[i]];
    if (loc[i] < count[i+1]) {
      live++;
    }
  }
  live--;
  // Perform sort
  for (int i=0; i<n; i++) {
    int64_t val = unsorted[live];
    int64_t d = (val>>bit) & mask;
    array[loc[d]] = val;
    loc[d]++;
    unsorted[live] = array[loc[d]];
    if (loc[d] == count[d+1]) {
      live--;
    }
  }
  if (bit>0) {
    for (int i=0; i<8; i++) {
      n = count[i+1] - count[i];
      if (n > 20) { // If replaced by n > 1, insertion_sort is not needed.
        msd_sort(array + count[i], n, bit-3);
      } else {
        insertion_sort(array + count[i], n);
      }
    }
  }
}

void lsd_sort(int64_t * array, int n) {
  const int64_t mask = INT64_C(7);
  std::vector<int64_t> buffer(n);
  for (int64_t bit=0; bit<63; bit+=3) {
    // Copy and count
    int count[9]={};
    for (int i=0; i<n; i++) {
      buffer[i] = array[i];
      count[((array[i]>>bit) & mask) + 1]++;
    }
    // Init writer positions
    for (int i=0; i<8; i++) {
      count[i+1]+=count[i];
    }
    // Perform sort
    for (int i=0; i<n; i++) {
      int64_t val = buffer[i];
      int64_t d = (val>>bit) & mask;
      array[count[d]] = val;
      count[d]++;
    }
  }
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Radix sort most significant first or least significant, which is faster?

From Dev

most significant v.s. least significant radix sort

From Dev

Efficient least significant set bit of "biginteger" class

From Dev

Clearing least significant bit

From Dev

Least significant bit mips

From Dev

How to write least significant bit into the buffer?

From Dev

How to Delete Least Significant Bit in Java?

From Dev

How to clear most significant bit in byte?

From Dev

Getting least significant bit in JavaScript

From Dev

Extraction of the least significant bit of a pixel

From Dev

set most significant bit in C

From Dev

Writing a bit reader in JAVA (32-bit little-endian most-to-least-significant bit packing)

From Dev

sorting 1-bit array using radix sort?

From Dev

How can I get the value of the least significant bit in a number?

From Dev

How to Replace Least Significant Bit In Buffered Image in Scala

From Dev

Fast way of finding most and least significant bit set in a 64-bit integer

From Dev

Index of second least significant set bit

From Dev

Change the least significant bit (LSB) in java

From Dev

Overwriting least-significant bit in a Word

From Dev

Change the least significant bit (LSB) in java

From Dev

fastest way to access the least significant bit of an integer?

From Dev

How do I flip the most significant bit in MIPS?

From Dev

Find most significant set bit in a long

From Dev

Comparing the Most Significant Bit of two numbers: ==, <, <=

From Dev

Get the most significant bit from an 8-bit value

From Dev

Get the most significant bit from an 8-bit value

From Dev

Which one-bit integer has more significant bit?

From Dev

Xor starting with the significant bit

From Dev

performance characteristics of radix sort

Related Related

  1. 1

    Radix sort most significant first or least significant, which is faster?

  2. 2

    most significant v.s. least significant radix sort

  3. 3

    Efficient least significant set bit of "biginteger" class

  4. 4

    Clearing least significant bit

  5. 5

    Least significant bit mips

  6. 6

    How to write least significant bit into the buffer?

  7. 7

    How to Delete Least Significant Bit in Java?

  8. 8

    How to clear most significant bit in byte?

  9. 9

    Getting least significant bit in JavaScript

  10. 10

    Extraction of the least significant bit of a pixel

  11. 11

    set most significant bit in C

  12. 12

    Writing a bit reader in JAVA (32-bit little-endian most-to-least-significant bit packing)

  13. 13

    sorting 1-bit array using radix sort?

  14. 14

    How can I get the value of the least significant bit in a number?

  15. 15

    How to Replace Least Significant Bit In Buffered Image in Scala

  16. 16

    Fast way of finding most and least significant bit set in a 64-bit integer

  17. 17

    Index of second least significant set bit

  18. 18

    Change the least significant bit (LSB) in java

  19. 19

    Overwriting least-significant bit in a Word

  20. 20

    Change the least significant bit (LSB) in java

  21. 21

    fastest way to access the least significant bit of an integer?

  22. 22

    How do I flip the most significant bit in MIPS?

  23. 23

    Find most significant set bit in a long

  24. 24

    Comparing the Most Significant Bit of two numbers: ==, <, <=

  25. 25

    Get the most significant bit from an 8-bit value

  26. 26

    Get the most significant bit from an 8-bit value

  27. 27

    Which one-bit integer has more significant bit?

  28. 28

    Xor starting with the significant bit

  29. 29

    performance characteristics of radix sort

HotTag

Archive