【问题标题】:How Sorting Networks Built By Hand如何手动构建排序网络
【发布时间】:2014-11-08 10:08:59
【问题描述】:

有很多 4 元素、6 元素(输入)... 16 输入排序网络,但我需要 32 输入版本 拥有 32x32 剪切排序算法(我计划作为 Opencl 辅助功能)拥有 1024x1024 剪切排序 opencl 算法。如何导出我的 32 输入排序网络?

  • 也许是某种进化算法可以最大限度地减少交换次数,我在 opencl 代码中使用它?
  • 有固定的规则吗?
  • 还是只是通过反复试验发现的?

    Input array: 1M elements ----> 1024x1024  2D matrix with inverted odd-rows (shear)
    
                 each row(1024) of matrix  --------> 32 x 32 2D matrix (shear)
    
                       32 element row ---------> Sorting  (network)
    
     Each thread computes one row of 1024 elements. So only 1024 threads for 1M element array.
    

我计划在网络中使用的非发散比较是:

     if(a>b)              // where a and b are between 0 and 16M
          swap(a,b)

     becomes

      a0=a; b0=b; // saving

      c = a-b 
      d = !(sign bit of c)  (0 for negative,  1 for positive)
      tmp=b*d;      //tmp=a if a>b  otherwise 0
      a=a*d         //a=b   if a>b  otherwise 0
      b=tmp*d;      //b=tmp   if a>b otherwise 0

      // a0 is backup of a, b0 is backup of b
      e = (sign bit of c)  (1 for negative,  0 for positive)
      tmp0=a0*e;      //tmp0=a0 if a0<=b0  otherwise 0
      a0=b0*e         //a0=b0   if a0<=b0  otherwise 0
      b0=tmp0*e;      //b0=tmp0   if a0<=b0 otherwise 0

      aOut=a+a0;      // only a or a0 can be different than zero
      bOut=b+b0;      // only b or b0 can be different than zero

我确定这不是最快的,但我需要进行快速简单的排序以尝试我的粒子约束求解器,该求解器为固定空间索引(网格)尖叫排序,我有 1M 粒子并尝试剪切网络排序的剪切.

为了验证剪切排序,我在每个线程的基础上实现了 32 输入排序串行双调排序器,以构建每列和行排序的 32x32 矩阵。所以 32x32 = 1024 元素排序需要 9 毫秒,这对于 32 核 @ 700 MHz 来说太慢了。

1024 元素排序需要 9 毫秒,每次 1024 排序后至少需要 20 次迭代才能对 1M 数组进行排序。即使它得到 90 毫秒,这对于仅按键来说也太慢了。会有很多值绑定到键上。(超过 100 个)

尝试用冒泡排序代替双调,得到了 10 毫秒,所以问题一定出在剪切排序实现中吗?

【问题讨论】:

    标签: sorting optimization comparison shearsort sorting-network


    【解决方案1】:

    我发现了一些有价值的信息,称为Hasse Diagrams。阅读它,但解决需要一些时间(也许我永远无法)所以我搜索并找到下面已经完成的解决方案:

    N=32 的网络,使用 Batcher 的 Merge-Exchange。 (192 个比较器) http://jgamble.ripco.net/cgi-bin/nw.cgi?inputs=32&algorithm=batcher&output=svg

    使用它对每个 32 个元素的 32 个数组进行排序(没有 for 循环,只是手写比较器),并在 32 个内核上应用剪切排序,与双音排序(for 循环)+剪切排序相比,内核时间从 9 毫秒减少到 2 毫秒(for循环和并行)。

    这是从 for-looped bitonic sorter 到 non-loop Batcher's Merge Exchange 的 4 倍加速。

    从这里:

       void MergeSort32(int * RegisterArray, int dir)"
                {"
                     int n=32;"
                     for (int s=2; s <= n; s*=2) 
                     {
                            for (int i=0; i < n;) 
                            {
                                 merge_up((RegisterArray+i),s,dir);
                                 merge_down((RegisterArray+i+s),s,dir);
                                 i += s*2;
                             }
                      }
                }
    

      swapx(arr,0,16,dir);
      swapx(arr,1,17,dir);
      swapx(arr,2,18,dir);
      swapx(arr,3,19,dir);
      swapx(arr,4,20,dir);
      swapx(arr,5,21,dir);
      swapx(arr,6,22,dir);
      swapx(arr,7,23,dir);
      ...
      ... 191 lines of branchless comparators-swappers 
      (branching version crashes for some reason, maybe because of 
       inlined 382 if sentences per core
       xor swap idiom shouldnt be a problem.)
    

    但是 opencl 编译时间从 0.5 秒增加到 7.5 秒。 在选项中添加 -cl-opt-disable 会导致永远编译,直到我 ctrl+alt+del。所以自动优化选项也必须优化编译部分。

    编辑: 剪切排序(1M)由 Batcher 的剪切排序(每个 1k)构建(每个 32 个元素):0.341 秒。 HD7870,每个工作组使用 64 个线程。排序工作经过验证,但比单核 cpu shell 排序慢得多(0.050 秒)。

    【讨论】:

      【解决方案2】:

      目前,已知使用最少比较交换单元对 32 个元素进行排序的排序网络的工作方式如下:使用 most efficient sorting network of size 16 对前 16 个元素进行排序,对以下 16 个元素执行相同操作,然后使用合并步骤来自Batcher's odd-even mergesort。基本上,它给出了以下几对比较交换单元:

      对数组的前半部分进行排序:

      [0,1],[2,3],[4,5],[6,7],[8,9],[10,11],[12,13],[14,15],
      [0,2],[4,6],[8,10],[12,14],[1,3],[5,7],[9,11],[13,15],
      [0,4],[8,12],[1,5],[9,13],[2,6],[10,14],[3,7],[11,15],
      [0,8],[1,9],[2,10],[3,11],[4,12],[5,13],[6,14],[7,15],
      [5,10],[6,9],[3,12],[13,14],[7,11],[1,2],[4,8],
      [1,4],[7,13],[2,8],[11,14],[5,6],[9,10],
      [2,4],[11,13],[3,8],[7,12],
      [6,8],[10,12],[3,5],[7,9],
      [3,4],[5,6],[7,8],[9,10],[11,12],
      [6,7],[8,9]
      

      对数组的后半部分进行排序:

      [16,17],[18,19],[20,21],[22,23],[24,25],[26,27],[28,29],[30,31],
      [16,18],[20,22],[24,26],[28,30],[17,19],[21,23],[25,27],[29,31],
      [16,20],[24,28],[17,21],[25,29],[18,22],[26,30],[19,23],[27,31],
      [16,24],[17,25],[18,26],[19,27],[20,28],[21,29],[22,30],[23,31],
      [21,26],[22,25],[19,28],[29,30],[23,27],[17,18],[20,24],
      [17,20],[23,29],[18,24],[27,30],[21,22],[25,26],
      [18,20],[27,29],[19,24],[23,28],
      [22,24],[26,28],[19,21],[23,25],
      [19,20],[21,22],[23,24],[25,26],[27,28],
      [22,23],[24,25]
      

      奇偶合并数组的两半:

      [0, 16],
      [8, 24],
      [8, 16],
      [4, 20],
      [12, 28],
      [12, 20],
      [4, 8],
      [12, 16],
      [20, 24],
      [2, 18],
      [10, 26],
      [10, 18],
      [6, 22],
      [14, 30],
      [14, 22],
      [6, 10],
      [14, 18],
      [22, 26],
      [2, 4],
      [6, 8],
      [10, 12],
      [14, 16],
      [18, 20],
      [22, 24],
      [26, 28],
      [1, 17],
      [9, 25],
      [9, 17],
      [5, 21],
      [13, 29],
      [13, 21],
      [5, 9],
      [13, 17],
      [21, 25],
      [3, 19],
      [11, 27],
      [11, 19],
      [7, 23],
      [15, 31],
      [15, 23],
      [7, 11],
      [15, 19],
      [23, 27],
      [3, 5],
      [7, 9],
      [11, 13],
      [15, 17],
      [19, 21],
      [23, 25],
      [27, 29],
      [1, 2],
      [3, 4],
      [5, 6],
      [7, 8],
      [9, 10],
      [11, 12],
      [13, 14],
      [15, 16],
      [17, 18],
      [19, 20],
      [21, 22],
      [23, 24],
      [25, 26],
      [27, 28],
      [29, 30]
      

      我使用 Wikipedia 页面上给出的 oddeven_merge 算法生成了先前的索引对。我不能保证它会比你已经拥有的更快,但它至少会将比较交换单元的数量从 191 个(使用 Batcher 的奇偶合并排序)降低到 185 个。我已经阅读了有关此事的研究论文而且似乎我们目前不知道使用少于 185 个比较器的排序网络可以对 32 个元素进行排序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多