Алгоритм делит исходный массив на P частей по количеству выделенных программе 
процессоров. Части сортируются параллельно и независимо друг от друга, каждая 
стандартным последовательным алгоритмом на своём процессоре. Затем (после 
того как все потоки, выполнявшие раздельную сортировку, 
завершатся) все части сливаются в один отсортированный массив, причем 
процедура слияния также распараллеливается.
//Слияние двух расположенных рядом друг с другом частей массива
void 
merge(int *A, int *B, int l, int m, int r)
//A - сортируемый массив, B - 
буфер для слияния, l - первый элемент первой части, r - последний элемент второй 
части, m - последний элемент первой части
{
 int i=l;
 int j 
= m+1;
 int k=l;
 //Вставлять минимальные элементы в B пока не 
кончится одна из последовательностей
 while (( i<=m) && 
(j<= r))
 {
  if 
(A[i]  {
   B[k] = 
A[i];
   i++;
  } else 
{
   B[k] = 
A[j];
   j++;
  }
  k++;
 }
 //Скопировать 
остаток, если таковой имеется
 while (i <    = 
m)
 {
  B[k]=A[i];
  k++;
  i++;
 }
 while (j <   
 = 
r)
 {
  B[k]=A[j];
  k++;
  j++;
 }
 //Отсортированная 
часть остаётся в B
}
//Сортировка слиянием, без рекурсии
void nrmsort(int* A, int* B, int l, 
int r)
//A - сортируемый массив, B - буфер для слияния, l - левая граница 
сортируемого участка, r - правая граница
{
 int p=2;
 int 
m;
 int i;
 int r2;
 int N = r-l+1;
 int *tA = 
A;
 int *tB = B;
 int *t = NULL;
 
 while(p<(2*N))
 {
  for(i=l;i<=r;i+=p)
  {
   r2 = 
 min(i+p-1,r);
   m = min(r,((i+i+p-1)  >>        
1)); 
   merge(tA,tB,i,m,r2);
  }
  p *= 
 2; //Вдвое увеличим размер сливаемых частей
  t = tA; 
//Поменяем сортируемый массив и буфер местами
  tA = 
tB;
  tB = t;
  t =     NULL;
 }
 if (tA !=  
 A)
 {
  //Переписать элементы в исходный массив 
А
  for (int k = l; k<= r; 
k++)
  {
   A[k] = 
B[k];
  }
 }
}
//Сортировка слиянием, распараллеленная
void mp_sort(int* A, int* B, int 
N, int P)
//A - сортируемый массив, B - буфер для слияния, N - размер 
массива, P - число параллельно 
выполняемых потоков
{
 int *tA = A;
 int *tB = 
B;
 int *t =   NULL;
 //1)Разбиение на блоки и сортировка их по 
отдельности
 int i;
 int part_size = 
(int)ceil((float)N/(float)P);
  #pragma omp parallel shared(P, 
tA, tB, N, part_size)
 #pragma omp for private(i) 
 for(i=0;i
 {
  nrmsort(tA,tB,i*part_size,min((i+1)*part_size,N-1));
 }
 int 
r2,m;
 while (part_size <     
(2*N))
 {
  #pragma omp parallel 
shared(P, tA, tB, N, part_size)
  #pragma omp for 
private(i,r2,m)
  for(i=0;i  {
   r2 = 
 min(i+part_size-1,N-1);
   m = 
((i+i+part_size-1)  
>>  
  
    
1); 
   merge(tA,tB,i,m,r2);
  }
  part_size 
*= 2;
  t = tA;
  tA = tB;
  tB = 
t;
  t = NULL;
 }
 if (tA != 
A)
 {
  //Переписать элементы в исходный массив 
А
  int k;
  #pragma omp parallel shared(A,B,N)
  #pragma omp for 
private(k)
  for (k = 0; k< N; 
k++)
  {
   A[k] = 
B[k];
  }
 }
}