首页 > 解决方案 > 16 个嵌套 For 循环加速 C++/Rcpp

问题描述

我有一个计算量非常大的程序,我需要运行 16 个嵌套的 for 循环,以完成对 16 个数字向量的所有可能排列的迭代检查,每个数字向量的大小为 26。我的第一次尝试是使用R(我的首选语言),但很快就被重定向了通过C++Rcpp。我可以在我的 PC 上本地运行代码(4 核,Intel i7-6600U CPU @ 2.60GHz,16GB RAM),但也可以访问 Azure 云计算,并且可以启动任何规模的集群。

我当前的代码如下所示:

#include <Rcpp.h>
#include <math.h>
#include <iostream>
using namespace Rcpp;

// [[Rcpp::export]]
NumericMatrix optimalIndex(NumericVector a, NumericVector b, NumericVector c, NumericVector d, NumericVector e, NumericVector f,
                           NumericVector g, NumericVector h, NumericVector i, NumericVector j, NumericVector k, NumericVector l,
                           NumericVector m, NumericVector n, NumericVector o, NumericVector p){
  NumericMatrix outp(1000000, 16);
  int index = 0;
  int minsum = 0;
  for(int c1 = 0; c1 < a.size(); c1++){
    for(int c2 = 0; c2 < b.size(); c2++){
      for(int c3 = 0; c3 < c.size(); c3++){
        for(int c4 = 0; c4 < d.size(); c4++){
          for(int c5 = 0; c5 < e.size(); c5++){
            for(int c6 = 0; c6 < f.size(); c6++){
              for(int c7 = 0; c7 < g.size(); c7++){
                for(int c8 = 0; c8 < h.size(); c8++){
                  for(int c9 = 0; c9 < i.size(); c9++){
                    for(int c10 = 0; c10 < j.size(); c10++){
                      for(int c11 = 0; c11 < k.size(); c11++){
                        for(int c12 = 0; c12 < l.size(); c12++){
                          for(int c13 = 0; c13 < m.size(); c13++){
                            for(int c14 = 0; c14 < n.size(); c14++){
                              for(int c15 = 0; c15 < o.size(); c15++){
                                for(int c16 = 0; c16 < p.size(); c16++){
                                  minsum = a(c1) + b(c2) + c(c3) + d(c4) + e(c5) + f(c6)
                                            + g(c7) + h(c8) + i(c9) + j(c10) + k(c11) + l(c12)
                                            + m(c13) + n(c14) + o(c15) + p(c16);
                                  if(minsum == 0){
                                    outp(index, 0) = c1;
                                    outp(index, 1) = c2;
                                    outp(index, 2) = c3;
                                    outp(index, 3) = c4;
                                    outp(index, 4) = c5;
                                    outp(index, 5) = c6;
                                    outp(index, 6) = c7;
                                    outp(index, 7) = c8;
                                    outp(index, 8) = c9;
                                    outp(index, 9) = c10;
                                    outp(index, 10) = c11;
                                    outp(index, 11) = c12;
                                    outp(index, 12) = c13;
                                    outp(index, 13) = c14;
                                    outp(index, 14) = c15;
                                    outp(index, 15) = c16;
                                    outp(index, 16) = c17;
                                    outp(index, 17) = c18;
                                    outp(index, 18) = c19;
                                    outp(index, 19) = c20;
                                    outp(index, 20) = c21;
                                    outp(index, 21) = c22;
                                    outp(index, 22) = c23;
                                    outp(index, 23) = c24;
                                    outp(index, 24) = c25;
                                    outp(index, 25) = c26;
                                    outp(index, 26) = c27;
                                    outp(index, 27) = c28;
                                    outp(index, 28) = c29;
                                    outp(index, 29) = c30;
                                    outp(index, 30) = c31;
                                    index++;
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  return(outp);
}

这个函数的输出维度,outp,此时是未知的,所以我随意选择了 100 万行。我想返回行和与指定条件匹配的每一列的索引,即。= 0。

显然,这需要几年的时间来运行。我不确定并行化是否是此循环的一个选项,或者我可以使用哪些其他方法来提高速度。就像我说的,如果可以的话,我可以在 Azure 中运行更多内核和/或更多内存。

有没有更好/更快的方法来做到这一点?

标签: c++rfor-loopnested-loopsrcpp

解决方案


我认为不可能在合理的时间内运行这个程序,因为 26^16 等于 43,608,742,899,428,874,059,776。我认为使用状态为 dp[SUM][letterIndex] 的动态编程可以更快地解决这个问题。您可以预先计算有多少个字母组合,总和等于 SUM 并使用 letterIndex 字母。此解决方案的复杂性为 O(26*16*MAX),其中 MAX 是向量中的最大值。当然,如果向量中的数字是整数,这是有效的。


推荐阅读