Project: ArangoDB (App Definition and Development / Database)
File: block_indirect_sort_en.pdf

BLOCK INDIRECT
A new parallel sorting algorithm
 Francisco Jose Tapia
fjtapia  @  gmail  .  com
BRIEF
Modern processors obtain their power increasing the number of “cores” or HW threads, which permit them to
execute several processes simultaneously, with a shared memory structure.
SPEED OR LOW MEMORY
In the parallel sorting algorithms, we can find two categories .
SUBDIVISION ALGORITHMS   
Filter the data and generate two or more parts. Each part obtained is filtered and divided by other threads,
until the size of the data to sort is smaller than a predefined size, then it is sorted by a single thread. The
algorithm most frequently used in the filter and sort is quick sort.
These algorithms are fast with a small number of threads, but inefficient with a large number of HW threads.
Examples of this category are :
◦Intel Threading Building Blocks (TBB)
◦Microsoft PPL Parallel Sort.
MERGING ALGORITHMS
Divide the data into many parts at the beginning, and sort each part with a separate thread. When the parts
are sorted, merge them to obtain the final result. These algorithms need additional memory for the merge,
usually an amount equal to the size of the input data.
With a small number of threads, these algorithms usually have similar speed to the subdivision algorithms,
but with many threads they are much faster . Examples of this category are :
◦GCC Parallel Sort (based on OpenMP)
◦Microsoft PPL Parallel Buffered Sort
SPEED AND LOW MEMORY
This new algorithm is an unstable parallel sort algorithm, created for processors connected with shared
memory. This provides excellent performance in machines with many HW threads, similar to the GCC
Parallel Sort, and better than TBB, with the additional advantage of lower memory consumption.
This algorithm uses as auxiliary memory a block_size elements buffer for each thread. The block_size is an
internal parameter of the algorithm, which, in order to achieve the highest speed, change according the size
of the objects to sort according the next table. The strings use a block_size of 128.
object size 1 - 1516 - 3132 - 6364 - 127128 - 255256 - 511512 - 
block_size 409620481024768512256128
The worst case memory usage for the algorithm is when elements are large and there are many threads.
With big elements (512 bytes), and 12 threads, the memory measured was:
•GCC Parallel Sort  1565 MB
•Threading Building Blocks (TBB)   783 MB
•Block Indirect Sort    812 MB
Block Indirect  Sort - A new parallel sorting algorithm page : 1INDEX
1.- OVERVIEW OF THE PARALLEL SORTING ALGORITHMS
2.- INTERNAL DESCRIPTION OF THE ALGORITHM
2.1.- SUBDIVISION OF THE MERGE
2.2.- NUMBER OF ELEMENTS NO MULTIPLE OF THE BLOCK SIZE.
2.3.- INDIRECT SORTING
2.4.- IN PLACE REARRANGEMENT FROM A INDEX (BLOCK SORTING)
2.5- SEQUENCE PARALLELIZATION
3.- BENCHMARKS
3.1.- INTRODUCTION
3.2.- DESCRIPTION
3.3.- LINUX 64 GCC 5.2 Benchmarks
3.3.1.- Single Thread Algorithms
3.3.2.- Parallel Algorithms
3.4.- Windows 10  VISUAL STUDIO 2015 x64 Benchmarks
3.4.1.- Single Thread Algorithms
3.4.2.- Parallel Algorithms
4.- BIBLIOGRAPHY
5.- GRATITUDE
Block Indirect  Sort - A new parallel sorting algorithm page : 21.- OVERVIEW OF THE PARALLEL SORTING
     ALGORITHMS
Among the unstable parallel sorting algorithms, there are basically two types:
1.- SUBDIVISION ALGORITHMS
As Parallel Quick Sort.  One thread divides the problem in two parts. Each part obtained is divided by
other threads, until the subdivision generates sufficient parts to keep all the threads buys.  The below
example shows that this means with a 32 HW threads processor, with N elements to sort.
Step
1
2
3
4
5
6Threads working
1
2
4
8
16
32Threads waiting
31
30
28
24
16
0Elements to process by each thread
 N
 N / 2
 N / 4
 N / 8
 N / 16
 N / 32
Very even splitting would be unusual in reality, where most subdivisions are uneven
This algorithm is very fast and don't need additional memory, but the performance is not good when
the number of threads grows. In the table before, until the 6th division, don't have work for to have
busy all the HW threads, with the additional problem  that the first division is the hardest, because the
number of elements is very large.
2.- MERGING ALGORITHMS,
Divide the data into many parts at the beginning, and sort each part with a separate thread. When
the parts are sorted, merge them to obtain the final result. These algorithms need additional memory
for the merge, usually an amount equal to the size of the input data.
These algorithms provide the best performance with many threads, but their performance with a low
number of threads is worse than the subdivision algorithms.
2.- INTERNAL DESCRIPTION OF THE ALGORITHM
This new algorithm (Block Indirect), is a merging algorithm. It has similar performance to GCC Parallel Sort
With  many  threads,  but  using  a low  amount  of  additional memory,  close  to  that  used  by  subdivision
algorithms.
Internally, the algorithm, manage blocks of elements. The number of elements of the block (block_size),
change according the size of the objects to sort according the next table. The strings use a block_size of
128.
object size 1 - 1516 - 3132 - 6364 - 127128 - 255256 - 511512 - 
block_size 409620481024768512256128
This new algorithm only need an auxiliary memory of one block of elements for each HW thread. The worst
case memory usage for the algorithm is when elements are large and there are many threads. With big
elements (512 bytes), and 12 threads, the memory measured was:
•GCC Parallel Sort  1565 MB
•Threading Building Blocks (TBB)   783 MB
•Block Indirect Sort    812 MB
Block Indirect  Sort - A new parallel sorting algorithm page : 3These algorithms are not optimal when using just 1 thread, but are easily parallelized, and need only a small
amount of auxiliary memory.
The algorithm divide the number of elements in a number of parts that is the first power of two greater than
or equal to the number of threads to use. ( For example: with 3  threads, make 4 parts, for 9 threads make 16
parts…) Each part obtained is sorted by the parallel intro sort algorithm.
12345678910111213141516
1-23-45-67-89-1011-1213-1415-16
1-2-3-4 5-6-7-8 9-10-11-12 13-14-15-16
1-2-3-4-5-6-7-8 9-10-11-12-13-14-15-16
1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16
With the sorted parts, merge pairs of parts. We consider the elements are in blocks of fixed size. We initially
restrict the number of elements to sort (N) to a multiple of the block size. For to explain the algorithm, I use
several examples with a block size of 4. Each thread receives a number of blocks to sort, and when
complete we have a succession of blocks sorted.
For the merge, we have two successions of block sorted. We sort the blocks of the two parts the first element
of the block. This merge is not fully sorted, is sorted only by the first element. We call this First Merge
But if we merge the first block with the second, the second with the third and this successively, we will obtain
a new list fully sorted with a size of the sum of the blocks of the first part plus the blocks of the second part.
This merge algorithm, only need an auxiliary memory of the size of a block.
Part 1Part 2First
mergePass 1Pass 2Pass 3Pass 4Final
Merge
2
5
9
102
3
4
52
3
4
5
2
5
9
103
4
6
73
4
6
76
7
9
106
7
8
96
7
8
9
12
28
32
348
11
13
148
11
13
1410
11
13
1410
11
12
1310
11
12
13
35
37
39
4016
20
27
2912
28
32
3414
28
32
3414
16
20
2714
16
20
27
44
46
50
7136
38
45
6016
20
27
2928
29
32
3428
29
32
34
35
37
39
4035
36
37
3835
36
37
38
36
38
45
6039
40
45
6039
40
44
4539
40
44
45
44
46
50
7146
50
60
7146
50
60
71
Block Indirect  Sort - A new parallel sorting algorithm page : 4The idea which make interesting this algorithm, is that you can divide, in an easy way, the total number of
blocks to merge,  in several parts, obtaining several groups of blocks, independents between them, which
can be merged in parallel.
2.1.- MERGE SUBDIVISION
Suppose, we have the next first merge, with block size of 4, and want to divide in two independent parts, to
be executed by different threads.
To divide, we must looking for a border between two blocks of different color. And make the merge between
them. In the example, to obtain parts of similar size , we can cut in the frontier 4-5, or in the border 5 -6,
being the two options.
Block
NumberFirst
MergeOption 1
Border 4 -5Option 2
Border 5-6
010
12
14
2010
12
14
2010
12
14
20
121
70
85
20021
70
85
20021
70
85
200
222
24
28
3022
24
28
3022
24
28
30
331
35
37
4031
35
37
4031
35
37
40
441
43
45
5041
43
45
5041
43
45
50
5201
470
890
2000201
470
890
2000201
210
212
216
6210
212
216
220210
212
216
220220
470
890
2000
7221
224
227
230221
224
227
230221
224
227
230
82100
2104
2106
21102100
2104
2106
21102100
2104
2106
2110
92120
2124
2126
21302120
2124
2126
21302120
2124
2126
2130
In the option 1, the frontier is between the blocks 4 and 5, and the last of the block 4 is less or equal than the 
first of the block 5, and don't need merge. We have two parts, which can be merged in a parallel way The 
first with the blocks 0 to 4, and the second with the 5 to 9.
Block Indirect  Sort - A new parallel sorting algorithm page : 5In the option 2, the frontier is between the blocks 5 and 6, and the last of the block 5 is greater than the first
of the block 6, and we must do the merge of the two blocks, and appear new values for the blocks 5 and 6.
Then we have two parts, which can be merged in a parallel way. The first with the blocks from 0 to 5, and the
second with the 6 to 9.
2.2.- NUMBER OF ELEMENTS NOT MULTIPLE OF THE BLOCK 
SIZE
Until now, we assumed the number of elements is a multiple of the block size. When this is not true, we
configure the blocks, beginning for the position 0, and at end we have an incomplete block called tail. The tail
block always is in the last part to merge. We use a special operation just for this block, described in the next
example :
We have two groups of blocks A and B, with NA and NB blocks respectively. The tail block, if exist, always is
in the group B. Merge the tail block with the last block of the group A. With the merge two cases appear
shown in the next examples:
Case 1: The first value of the NA block don't change, and don't do nothing with the blocks.
Group AGroup B
Merge of
the blocks
NA and NBGroup A Group B
     NA -134
35
38
3928
29
36
41     NA-134
35
38
3928
29
36
41
       NA40
50
56
70         
NB-146
47
49
51     NA40
50
52
54           
NB -146
47
49
51
         
NB52
54      NB56
70
Case 2: The first value of the block A, changes, and we delete the block of the group A and insert in the
group B, immediately before the tail block. With this operation we guarantee the tail block is the last
Group AGroup B
Merge of the blocks NA
and NB.
The first value of NA
change.
Take the NA block and
insert in the NB position.Group AGroup B
          
NA-126
27
36
37         
NB-211
12
13
15           
NA -126
27
36
37          NB-
211
12
13
15
          
NA40
50
56
70         
NB-116
17
19
20           
NB-116
17
19
20
NB22
24            
NB22
24
40
50
NB+156
70
Block Indirect  Sort - A new parallel sorting algorithm page : 62.3.- INDIRECT SORT
In today's computers, the main bottleneck is the data bus. When the process needs to manage memory in
memory different locations,  as in  the  parallel sorting  algorithms,  the data  bus limits  the  speed of  the
algorithm.
In the benchmarks done on a 32 HW threads, sorting  N elements of 64 Bytes of size requires the same time
as sorting N / 2  elements 128 bytes of size. The comparison is the same with the two sizes.
In the algorithm described, in each merge, the blocks are moved, to be merged in the next step. This slows
down the algorithm, due to the data bus bottleneck.
To avoid this, do an indirect merge. We have an index with the relative position of the blocks. This implies the
blocks to merge are not contiguous, but that doesn't change the validity of the algorithm.
When all the merges are complete, with this index we move the blocks, and have all the data sorted. This
block movement is done with a simple and parallel algorithm,
2.4.- IN PLACE REARRANGEMENT FROM A INDEX (BLOCK 
SORTING)
The tail block, if one exists, is always in the last position, and doesn't need to be moved. We move  blocks
with the same size using an index. The best way is to see with an example :
We have an unsorted  data vector (D) with numbers. We also have, an index  ( I ), which is a vector with the
relative position of the elements of D
D01234567
200500600900100400700800
I01234567
40512673
To move the data, we need an auxiliary variable (Aux) of the same size as the data. In this example  the data
is a number, but in the case of blocks, the variable must have the size of a block.
This can be a bit confusing. Here are the steps of the process :
•Aux = D[0], and after this we must find which element must be copied in the position D[0],  we find it
in the position 0 of the index, and it is the position 4.
•The next step is D[0] = D[4], and find the position to move to the position 4, in the position 4 of the
index, and this is the position 2.
•When doing this successively, once the new position obtained is the first position used, (in this
example is the 0), move to this position from the Aux variable, and the cycle is closed.
In this example the steps are:
Aux   D[0]←
D[0]  D[4] ←
D[4]  D[2] ←
D[2]  D[5] ←
D[5]  D[6] ←
D[6]  D[7] ←
D[7]  D[3] ←
D[3]  D[1] ←
D[1]  Aux ←
Block Indirect  Sort - A new parallel sorting algorithm page : 7If we follow the arrows, we see a closed cycle. This cycle has a sequence formed by the position of the
elements passed. In this example the sequence is  0, 4, 2, 5, 6, 7, 3, 1.
With small elements the sequence is useless, because instead of extracting the sequence, we can move the
data, and all is done. But with big elements, as the blocks used in this algorithm, the sequence are very
useful, because from the sequences, we generate the parallel work for the  threads.
There can be several cycles In an index, with their corresponding sequences. To extract the sequences,
begin with the index.
•If in a position, the content is the position, indicate this element is sorted, and don't need to be
moved.
•If it's different, this imply it's the beginning of a cycle,  and must extract the sequence, as described
before, and determine the positions visited in the index.
We can see with an example of an index with several cycles.
Data vector (D)
01234567891011121314
242320151210211719132218141116
Index (I)
01234567891011121314
51349123147118261010
Doing the procedure previously described,  find 3 sequences
•5, 3, 9, 8, 11, 6, 14, 0
•4, 12, 10, 2
•13, 1
In the real problems, usually appear a few long sequences, and many small sequences. This permits parallel
execution, but it's not very efficient, because a long sequence can keep one thread busy while the other
threads are waiting, because they are finished with the sort sequences. Or even worse, there can be just
one sequence.
To deal with this issue, the long sequences can be easily divided and done in parallel. This permit an optimal
parallelization.
2.5- SEQUENCE PARALLELIZATION
The procedure can be a bit confusing, so here’s an example:
Data vector (D)
01234567891011121314151617
10014070609000160805013015020170101103012040
Index vector (I)
01234567891011121314151617
51311151783274014169110612
If we extract the sequence, as described before, we find only one loop, and one sequence. This sequence is;
5 8 7 2 11 14 1 13 9 4 17 12 16 6 3 15 10 0
We want to divide in 3 sequences of 6 elements. Each sequence obtained are  independent between them
and can be done in parallel. The procedure is :
Block Indirect  Sort - A new parallel sorting algorithm page : 8Generate a fourth sequence with the contents on the last position of each sequence. In this example is
14 12 0
Now, consider the 3 sequences as independent and can be applied in parallel. We apply the sequences over
the vector of data (D), and when all are finished, apply the sequence obtained with the last position of the
sub sequences. And all is done
See this example:
The data vector is
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
100 140 70 60 90 00 160 80 50 130 150 20 170 10 110 30 120 40
Apply this sequence
5 8 7 2 11 14
The new data vector is
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
100 140 20 60 90 50 160 70 80 130 150 110 170 10 00 30 120 40
Apply this sequence
1 13 9 4 17 12
The new data vector is
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
100 10 20 60 40 50 160 70 80 90 150 110 140 13000 30 120 170
Apply this sequence
16 6 3 15 10 0
The new data vector is
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
12010 20 30 40 50 60 70 80 90 100 110 140 13000 150 160170
These 3 sub sequences can be done in parallel, because don't have any shared element.
Finally,  when the subsequences are been applied, we apply the last sequence, obtained with the last
positions of the sub sequences
14 12 0
The new data vector is fully sorted
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
00 10 20 30 40 50 60 70 80 90 100 110 120 130140 150 160170
Block Indirect  Sort - A new parallel sorting algorithm page : 93.- BENCHMARKS
3.1.- INTRODUC  T  ION
To benchmark this we use  the implementation proposed for the Boost Sort Parallel Library. It's pending of 
the final approval, due this can suffer some changes until the final version and definitive approval in the 
boost library. You can find in https  ://  github  .  com  /  fjtapia  /  sort  _  parallel.
If you want run the benchmarks in your machine, you can find the code, instructions and procedures in 
https  ://  github  .  com  /  fjtapia  /  sort  _  parallel  _  benchmark
For the comparison, we use these parallel algorithms:
1.GCC Parallel Sort
2.Intel TBB Parallel Sort
3.Block Indirect Sort
3.2.- DESCRIPTION
The benchmark are running in a   machine with a I7 5820 3.3 GHz 6 cores, 12 threads, quad channel
memory (2133 MHz) with Ubuntu and the GCC 5.2 compiler
The compiler used was the GCC  5.2  64 bits
The benchmark have  3 parts:
1.- Sort of 100000000 uint64_t numbers randomly generated. The utility of this benchmark is to see the 
speed with small elements with a very fast comparison.
2.- Sort of 10000000 of strings randomly filled. The comparison is no so easy as the integers.
3.- Sort of objects of several sizes. The objects are arrays of 64 bits numbers, randomly filled. We will check 
with arrays of 1 , 2 , 4, 8, 16, 32 and 64 numbers. 
Definition 
of the objectBytes Number of  
elements to sort 
 uint64_t [1] 8 100 000 000 
 uint64_t [2] 16 50 000 000 
 uint64_t [4] 32 25 000 000 
 uint64_t [8] 64 12 500 000 
 uint64_t [16] 128 6 250 000 
 uint64_t [32] 256 3 125 000 
 uint64_t [64] 512 1 562 500 
The C++ definition of the objects is 
template <uint32_t NN>
struct int_array
{   uint64_t M[NN];
};
The comparison between objects can be of two ways:
•Heavy comparison : The comparison is done with the sum of all the numbers of the array. In 
each comparison, make the sum. 
•Light comparison : It's done using only the first number of the array, as a key in a register. 
Block Indirect  Sort - A new parallel sorting algorithm page : 103.3.- LINUX 64 GCC 5.2 Benchmarks
The benchmark are running in a I7 5820 3.3 GHz 6 cores, 12 threads, quad channel memory (2133 MHz) 
with Ubuntu and the GCC 5.2 compiler.
3.3.1.-SINGLE THREAD ALGORITHMS
The algorithms involved in this benchmark are :
StableMemory used Comments
GCC sort noN + Log N
boost sort noN + Log N
GCC stable_sort yesN + N / 2 
Boost stable_sort yesN + N / 2 
Boost spreadsort yesN + Log NExtremely fast algorithm, only for integers, floats 
and strings
INTEGER BENCHMARKS  Sort of 100000000 64 bits numbers, randomly filled 
 TimeMemory 
 GCC sort 8.33 secs784 MB
 Boost sort 8.11 secs784 MB
 GCC stable sort 8.69 secs1176 MB
 Boost stable sort 8.75 secs1175 MB
 Boost Spreadsort 4.33 secs784 MB
STRINGS BENCHMARKS  Sort of 10 000 000 strings randomly filled
 TimeMemory 
 GCC sort 6.39 secs820 MB
 Boost sort 7.01 secs820 MB
 GCC stable sort 12.99 secs1132 MB
 Boost stable sort 9.17 secs976 MB
 Boost Spreadsort 2.44 secs820 MB
OBJECTS BENCHMARKS  Sorting of objects of different sizes. The objects are arrays of 64 bits numbers. 
This benchmark is done using two kinds of comparison.
Heavy comparison : The comparison is done with the sum of all the numbers of the array. In each 
comparison, make the sum.
8 
bytes16 
bytes32 
bytes 64 
bytes 128 
bytes256 
bytes512 
bytesMemory 
used
GCC sort 8.75 4.493.031.971.711.371.17783 MB
Boost sort 8.194.422.651.911.671.351.09783 MB
GCC stable_sort 10.235.673.672.942.62.492.341174 MB
Boost stable_sort 8.855.113.182.412.011.861.601174 MB
Block Indirect  Sort - A new parallel sorting algorithm page : 11Light comparison : It's done using only the first number of the array, as a key in a register.
8 
bytes16 
bytes32 
bytes64 
bytes 128 
bytes256 
bytes512 
bytesMemory 
used
GCC sort 8.694.312.351.501.230.860.79783 MB
Boost sort 8.184.042.251.451.240.880.76783 MB
GCC stable_sort 10.345.263.202.572.472.412.301174 MB
Boost stable_sort 8.924.592.511.941.681.681.501174 MB
3.3.2.-PARALLEL ALGORITHMS
The algorithms involved in this benchmark are :
Stable Memory used  Comments
GCC parallel sort No2N Based on OpenMP
TBB parallel sort NoN + LogN
Boost parallel sort NoN +block_size*num threads New parallel algorithm
GCC parallel stable sort Yes2 N Based on OpenMP
Boost parallel stable sort YesN / 2 
Boost sample sort Yes N
TBB parallel stable sort Yes NExperimental code, not in the TBB official
The block_size is an internal parameter of the algorithm, which in order to achieve the highest speed,
change according the size of the objects to sort according to the next table. The strings use a block_size of
128.
object size (bytes) 1 - 1516 - 3132 - 6364 - 127128 - 255256 - 511512 - 
block_size 409620481024768512256128
For the benchmark I use the next additional code:
•Threading Building Blocks ( TBB) 
•OpenMP 
•Threading Building Block experimental code (
https://software.intel.com/sites/default/files/managed/48/9b/parallel_stable_sort.zip  ) 
The most significant of this parallel benchmark is the comparison between the Parallel Sort algorithms. GCC
parallel sort is extremely fast with many cores, but need an auxiliary memory of the same size then the data.
In the other side Threading Building Blocks (TBB), is not so fast with many cores , but the auxiliary memory
is LogN.
The Boost Parallel Sort (internally named Block Indirect Sort), is a new algorithm created and implemented
by  the  author  for  this  library,  which  combine  the  speed  of  GCC  Parallel  sort,  with  a  small  memory
consumption (block_size elements for each thread). The worst case for this algorithm is when have very big
elements and many threads. With big elements (512 bytes), and 12 threads, The memory measured was:
GCC Parallel Sort (OpenMP) 1565 MB
Threading Building Blocks (TBB) 783 MB
Block Indirect Sort 812 MB
In machines with a small number of HW threads, TBB is faster than GCC, but with a great number of HW
threads GCC is more faster than TBB. Boost Parallel Sort have similar speed than GCC Parallel Sort with a
great number of HW threads, and similar speed to TBB with a small number. 
Block Indirect  Sort - A new parallel sorting algorithm page : 12INTEGER BENCHMARKS  Sort of 100 000 000 64 bits numbers, randomly filled
time 
( secs)memory 
(MB) 
OMP parallel_sort 1,251560
TBB parallel_sort 1,64783
Boost parallel_sort 1,08786
OMP parallel_stable_sort 1,561948
TBB parallel_stable_sort 1,561561
Boost sample_sort 1,191565
Boost parallel_stable_sort 1,541174
STRING BENCHMARK Sort of 10000000 strings randomly filled
time 
(secs)memory 
(MB) 
OMP parallel_sort 1,492040
TBB parallel_sort 1,84820
Boost parallel_sort 1,3822
OMP parallel_stable_sort 2,252040
TBB parallel_stable_sort 2,11131
Boost sample_sort 1,511134
Boost 
parallel_stable_sort2,1977
OBJECT BENCHMARKS  Sorting of objects of different sizes. The objects are arrays of 64 bits number. 
This benchmark is done using two kinds of comparison.
Heavy comparison : The comparison is done with the sum of all the numbers of the array. In each 
comparison, make the sum.
8 
bytes16 
bytes32 
bytes64 
bytes128 
bytes256 
bytes512 
bytesMemory
Used
OMP parallel_sort 1,270,720,560,450,410,390,321565
TBB parallel_sort 1,630,80,560,50,440,390,32783
Boost parallel_sort 1,130,670,530,470,430,410,34812
OMP 
parallel_stable_sort1,621,381,231,191,091,070,971954
TBB 
parallel_stable_sort1,581,020,810,760,730,730,711566
Boost sample_sort 1,150,790,630,620,620,610,61566
Boost 
parallel_stable_sort1,581,020,80,760,730,730,711175
Block Indirect  Sort - A new parallel sorting algorithm page : 13Light comparison : It's done using only the first number of the array, as a key in a register.
8 
bytes16 
bytes32 
bytes64 
bytes128 
bytes256 
bytes512 
bytesMemory
used 
OMP parallel_sort 1,240,710,480,410,380,350,321565
TBB parallel_sort 1,660,80,520,430,40,350,32783
Boost parallel_sort 1,110,650,490,430,410,370,34812
OMP 
parallel_stable_sort1,551,361,231,181,091,070,971954
TBB 
parallel_stable_sort1,580,910,750,720,710,720,711566
Boost 
parallel_stable_sort1,160,740,630,620,610,610,61566
Boost sample_sort 1,560,910,750,720,720,720,711175
3.4.- WINDOWS 10 VISUAL STUDIO 2015 x64 Benchmarks
The benchmark are running in a virtual machine with Windows 10 and 10 threads over a I7 5820 3.3 GHz 
with Visual Studio 2015 C++ compiler.
3.4.1.-SINGLE THREAD ALGORITHMS 
The algorithms involved in this benchmark are :
StableMemory used Comments
std::sort noN + Log N
boost sort noN + Log N
std::stable_sort yesN + N / 2 
Boost stable_sort yesN + N / 2 
Boost spreadsort yesN + Log NExtremely fast algorithm, only for integers, floats and 
strings
INTEGER BENCHMARKS  Sort of 100000000 64 bits numbers, randomly filled 
Time
(secs)Memory
(MB)
std::sort 13763
Boost sort 10,74763
std::stable_sort 14,941144
Boost stable_sort 13,371144
Boost spreadsort 9,58763
STRING BENCHMARKS  Sort of 10 000 000 strings randomly filled
Time
(secs)Memory
(MB)
std::sort 13,3862
Boost sort 13,6862
std::stable_sort 26,991015
Boost stable_sort 20,641015
Boost spreadsort 5,7862
Block Indirect  Sort - A new parallel sorting algorithm page : 14OBJECTS BENCHMARK  Sorting of objects of different sizes. The objects are arrays of 64 bits numbers. 
This benchmark is done using two kinds of comparison.
Heavy comparison : The comparison is done with the sum of all the numbers of the array. In each 
comparison, make the sum.
8 
bytes16 
bytes32 
bytes64 
bytes128 
bytes256 
bytes512 
bytesMemory
used
std::sort 13,366,984,22,582,872,372,29763
Boost sort 10,545,613,262,722,451,761,73763
std::stable_sort 15,498,475,473,973,853,552,991144
Boost stable_sort 13,118,865,064,163,93,063,321144
Light comparison : It's done using only the first number of the array, as a key in a register.
8 
bytes16 
bytes32 
bytes64 
bytes128 
bytes256 
bytes512 
bytesMemory
used
std::sort 14,157,264,332,691,921,981,73763
Boost sort 10,3352,991,851,531,461,4763
std::stable_sort 14,687,644,293,333,222,863,081144
Boost stable_sort 13,598,364,453,733,162,812,61144
3.4.2.-PARALLEL ALGORITHMS
The algorithms involved in this benchmark are :
Stable Memory used  Comments
PPL parallel sort No N
PPL parallel buffered sort No 2 N
Boost parallel sort NoN +block_size*num threads New parallel algorithm
Boost parallel stable sort YesN + N / 2 
Boost sample sort Yes 2 N
The block_size is an internal parameter of the algorithm, which in order to achieve the highest speed, 
change according the size of the objects to sort according to the next table. The strings use a block_size of 
128.
object size (bytes) 1 - 1516 - 3132 - 6364 - 127128 - 255256 - 511512 - 
block_size 409620481024768512256128
INTEGER BENCHMARKS  Sort of 100 000 000 64 bits numbers, randomly filled
Time
(secs)Memory
(MB)
PPL parallel sort 3,11764
PPL parallel buffered sort 1,741527
Boost parallel sort 2,1764
Boost sample sort 2,781511
Boost parallel stable sort 3,31145
Block Indirect  Sort - A new parallel sorting algorithm page : 15STRINGS BENCHMARK  Sort of 10000000 strings randomly filled
Time
(secs)Memory
(MB)
PPL parallel sort 3,76864
PPL parallel buffered sort 3,771169
Boost parallel sort 3,41866
Boost sample sort 3,741168
Boost parallel stable sort 5,71015
OBJECTS BENCHMARKS  Sorting of objects of different sizes. The objects are arrays of 64 bits number. 
This benchmark is done using two kinds of comparison.
Heavy comparison : The comparison is done with the sum of all the numbers of the array. In each 
comparison, make the sum.
8 
bytes16 
bytes32 
bytes64 
bytes128 
bytes256 
bytes512 
bytesMemory
used
PPL parallel sort 2,841,711,010,840,890,770,65764
PPL parallel 
buffered sort2,21,2920,880,981,320,821527
Boost parallel sort 1,930,820,90,720,770,680,69764
Boost sample sort 3,022,032,151,411,551,821,391526
Boost parallel 
stable sort3,362,671,621,451,381,191,371145
Light comparison : It's done using only the first number of the array, as a key in a register.
8 
bytes16 
bytes32 
bytes64 
bytes128 
bytes256 
bytes512 
bytesMemory
used
PPL parallel sort 3,11,370,970,70,610,580,57764
PPL parallel 
buffered sort2,311,390,90,881,10,891,441527
Boost parallel sort 2,151,210,70,720,410,510,54764
Boost sample sort 3,41,941,561,4121,411,961526
Boost parallel 
stable sort3,562,371,791,451,721,341,441145
Block Indirect  Sort - A new parallel sorting algorithm page : 164.- BIBLIOGRA PHY
•Introduction to Algorithms,  3rd Edition (Thomas H. Cormen, Charles E.  Leiserson, Ronald L. 
Rivest, Clifford Stein)
•Structured Parallel Programming: Patterns for Efficient Computation  (Michael McCool, James 
Reinders, Arch Robison)
•Algorithms + Data Structures = Programs  (Niklaus Wirth)
5.- GRATITUDE
To CESVIMA  (http  ://  www  .  cesvima  .  upm  .  es  /),   Centro  de  Cálculo  de  la  Universidad  Politécnica  de
Madrid.  When need machines for to tune this algorithm, I contacted with the investigation department of
many Universities of Madrid. Only them, help me.
To Hartmut Kaiser, Adjunct Professor of Computer Science at Louisiana State University. By their faith in my
work,
 
To Steven Ross,  by their infinite patience in the long way in the develop of this algorithm, and their wise
advises.
Block Indirect  Sort - A new parallel sorting algorithm page : 17