Advertisement
shobomaru

ParallelBitonicSort

Nov 24th, 2012
842
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.10 KB | None | 0 0
  1. // BitonicSort.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
  2. //
  3.  
  4. #include "stdafx.h"
  5.  
  6. //#include <stdlib.h>
  7. //#include <time.h>
  8. //#include <amp.h>
  9. //#include <ppl.h>
  10.  
  11. #define N ( 2097152 )
  12.  
  13. // 基本的なバイトニックソート
  14. void bitonicSort( int num, int *ary1 )
  15. {
  16.     // 2の冪乗でなければ計算しない
  17.     if( ( ( num - 1 ) & num ) != 0 )
  18.         return;
  19.  
  20.     for( int block = 2; block <= num; block *= 2 ) {
  21.         for( int step = block / 2; step >= 1; step /= 2 ) {
  22.             for( int idx = 0; idx < num; idx++ ) {
  23.                 int e = idx ^ step;
  24.                 if( e > idx ) {
  25.                     int v1 = ary1[ idx ];
  26.                     int v2 = ary1[ e ];
  27.                     if( ( idx & block ) != 0 ) {
  28.                         if( v1 < v2 ) {
  29.                             ary1[ e ] = v1;
  30.                             ary1[ idx ] = v2;
  31.                         }
  32.                     } else {
  33.                         if( v1 > v2 ) {
  34.                             ary1[ e ] = v1;
  35.                             ary1[ idx ] = v2;
  36.                         }
  37.                     }
  38.                 }
  39.             }
  40.         }
  41.     }
  42. }
  43.  
  44. // 条件分岐をできるだけ排したバイトニックソート
  45. void bitonicSort2( int num, int *ary1 )
  46. {
  47.     // 2の冪乗でなければ計算しない
  48.     if( ( ( num - 1 ) & num ) != 0 )
  49.         return;
  50.  
  51.     for( int block = 2; block <= num; block *= 2 ) {
  52.         for( int step = block / 2; step >= 1; step /= 2 ) {
  53.             unsigned int maskLow = (unsigned int)step - 1;
  54.             unsigned int maskHigh = 0xFFFFFFFF ^ maskLow;
  55.             for( int i = 0; i < num / 2; i++ ) {
  56.                 int idx = ( ( i & maskHigh ) << 1 ) | ( i & maskLow );
  57.                 int v1 = ary1[ idx ];
  58.                 int v2 = ary1[ idx + step ];
  59.                 int isAsc = ( ( idx & block ) != 0 ) ? 1 : 0;
  60.                 int isBigger = ( v1 > v2 ) ? 1 : 0;
  61.                 bool needSwap = ( ( isAsc + isBigger ) == 1 ) ? true : false;
  62.                 if( needSwap ) {
  63.                     ary1[ idx ] = v2;
  64.                     ary1[ idx + step ] = v1;
  65.                 }
  66.             }
  67.         }
  68.     }
  69. }
  70.  
  71. // OpenMPで並列化したバイトニックソート
  72. void bitonicSortOpenMP( int num, int *ary1 )
  73. {
  74.     // 2の冪乗でなければ計算しない
  75.     if( ( ( num - 1 ) & num ) != 0 )
  76.         return;
  77.  
  78.     for( int block = 2; block <= num; block *= 2 ) {
  79.         for( int step = block / 2; step >= 1; step /= 2 ) {
  80. #pragma omp parallel for
  81.             for( int idx = 0; idx < num; idx++ ) {
  82.                 int e = idx ^ step;
  83.                 if( e > idx ) {
  84.                     int v1 = ary1[ idx ];
  85.                     int v2 = ary1[ e ];
  86.                     if( ( idx & block ) != 0 ) {
  87.                         if( v1 < v2 ) {
  88.                             ary1[ e ] = v1;
  89.                             ary1[ idx ] = v2;
  90.                         }
  91.                     } else {
  92.                         if( v1 > v2 ) {
  93.                             ary1[ e ] = v1;
  94.                             ary1[ idx ] = v2;
  95.                         }
  96.                     }
  97.                 }
  98.             }
  99.         }
  100.     }
  101. }
  102.  
  103. // PPLで並列化したバイトニックソート
  104. void bitonicSortPPL( int num, int *ary1 )
  105. {
  106.     // 2の冪乗でなければ計算しない
  107.     if( ( ( num - 1 ) & num ) != 0 )
  108.         return;
  109.  
  110.     for( int block = 2; block <= num; block *= 2 ) {
  111.         for( int step = block / 2; step >= 1; step /= 2 ) {
  112.             concurrency::parallel_for( 0, num, 1, [&]( int idx )
  113.             {
  114.                 int e = idx ^ step;
  115.                 if( e > idx ) {
  116.                     int v1 = ary1[ idx ];
  117.                     int v2 = ary1[ e ];
  118.                     if( ( idx & block ) != 0 ) {
  119.                         if( v1 < v2 ) {
  120.                             ary1[ e ] = v1;
  121.                             ary1[ idx ] = v2;
  122.                         }
  123.                     } else {
  124.                         if( v1 > v2 ) {
  125.                             ary1[ e ] = v1;
  126.                             ary1[ idx ] = v2;
  127.                         }
  128.                     }
  129.                 }
  130.             } );
  131.         }
  132.     }
  133. }
  134.  
  135. // C++ AMPで並列化したバイトニックソート
  136. void bitonicSortAmp( int num, int *ary1 )
  137. {
  138.     // 2の冪乗でなければ計算しない
  139.     if( ( ( num - 1 ) & num ) != 0 )
  140.         return;
  141.  
  142.     concurrency::array_view< int, 1 > av1( num, ary1 );
  143.  
  144.     for( int block = 2; block <= num; block *= 2 ) {
  145.         for( int step = block / 2; step >= 1; step /= 2 ) {
  146.  
  147.             concurrency::extent< 1 > extent = av1.extent;
  148.  
  149.             concurrency::parallel_for_each(
  150.             extent,
  151.             [=]( concurrency::index< 1 > i ) restrict( amp )
  152.             {
  153.                 int idx = i[ 0 ];
  154.                 int e = idx ^ step;
  155.                 if( e > idx ) {
  156.                     int v1 = av1[ idx ];
  157.                     int v2 = av1[ e ];
  158.                     if( ( idx & block ) != 0 ) {
  159.                         if( v1 < v2 ) {
  160.                             av1[ e ] = v1;
  161.                             av1[ idx ] = v2;
  162.                         }
  163.                     } else {
  164.                         if( v1 > v2 ) {
  165.                             av1[ e ] = v1;
  166.                             av1[ idx ] = v2;
  167.                         }
  168.                     }
  169.                 }
  170.             } );
  171.         }
  172.     }
  173.  
  174.     av1.synchronize();
  175. }
  176.  
  177.  
  178. // C++ AMPで並列化したバイトニックソート 2
  179. void bitonicSort2Amp( int num, int *ary1 )
  180. {
  181.     // 2の冪乗でなければ計算しない
  182.     if( ( ( num - 1 ) & num ) != 0 )
  183.         return;
  184.  
  185.     concurrency::array_view< int, 1 > av1( num, ary1 );
  186.  
  187.     for( int block = 2; block <= num; block *= 2 ) {
  188.         for( int step = block / 2; step >= 1; step /= 2 ) {
  189.             unsigned int maskLow = (unsigned int)step - 1;
  190.             unsigned int maskHigh = 0xFFFFFFFF ^ maskLow;
  191.  
  192.             concurrency::extent< 1 > extent = av1.extent / 2;
  193.  
  194.             concurrency::parallel_for_each(
  195.             extent,
  196.             [=]( concurrency::index< 1 > i ) restrict( amp )
  197.             {
  198.                 int idx = ( ( i[ 0 ] & maskHigh ) << 1 ) | ( i[ 0 ] & maskLow );
  199.                 int v1 = av1[ idx ];
  200.                 int v2 = av1[ idx + step ];
  201.                 int isAsc = ( ( idx & block ) != 0 ) ? 1 : 0;
  202.                 int isBigger = ( v1 > v2 ) ? 1 : 0;
  203.                 bool needSwap = ( ( isAsc + isBigger ) == 1 ) ? true : false;
  204.                 if( needSwap ) {
  205.                     av1[ idx ] = v2;
  206.                     av1[ idx + step ] = v1;
  207.                 }
  208.             } );
  209.         }
  210.     }
  211.  
  212.     av1.synchronize();
  213. }
  214.  
  215.  
  216.  
  217.  
  218. void bench( int m )
  219. {
  220.     srand( 123456789 );
  221.  
  222.     int *ary1 = new int[ N ];
  223.     for( int i = 0; i < N; i++ ) {
  224.         ary1[ i ] = ( rand() >> 1 ) * ( rand() >> 1 ) * ( rand() >> 1 );
  225.     }
  226.  
  227.     clock_t start, end;
  228.     start = clock();
  229.  
  230.     switch( m ) {
  231.     case 1: bitonicSort( N, ary1 ); break;
  232.     case 2: bitonicSort2( N, ary1 ); break;
  233.     case 3: bitonicSortOpenMP( N, ary1 ); break;
  234.     case 4: bitonicSortPPL( N, ary1 ); break;
  235.     case 5: bitonicSortAmp( N, ary1 ); break;
  236.     case 6: bitonicSort2Amp( N, ary1 ); break;
  237.     default: throw "バグバグ";
  238.     }
  239.  
  240.     end = clock();
  241.     printf( "%d の実行時間は %f [sec]のようです\n",
  242.         m, ( (double)end - start ) / CLOCKS_PER_SEC );
  243.  
  244.     int prev = INT_MIN;
  245.     for( int i = 0; i < N; i++ ) {
  246.         //printf( "%d\n", ary1[ i ] );
  247.         if( prev > ary1[ i ] ) {
  248.             throw "ソートできてねぇだろボケェェェェェ";
  249.         }
  250.         prev = ary1[ i ];
  251.     }
  252.  
  253.     delete[] ary1;
  254. }
  255.  
  256. int main()
  257. {
  258.     bench( 1 );
  259.     bench( 2 );
  260.     bench( 3 );
  261.     bench( 4 );
  262.     //bench( 5 ); // error on Radeon GPU
  263.     bench( 6 );
  264.  
  265.     puts("おしまい");
  266.     return 0;
  267. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement