16 вложенных циклов For-Loops Speed ​​C ++ / Rcpp - PullRequest
1 голос
/ 26 мая 2020

У меня есть очень интенсивная вычислительная программа, которую мне нужно запустить для 16 вложенных циклов for, чтобы выполнить sh итеративную проверку всех возможных перестановок 16 числовых векторов каждый размером 26. Моя первая попытка была в R ( мой предпочтительный язык), но был быстро перенаправлен на C++ через пакет Rcpp. Я могу запустить код локально на своем P C (4-ядерный процессор Intel i7-6600U @ 2,60 ГГц, 16 ГБ ОЗУ), но также имею доступ к облачным вычислениям 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, на данный момент неизвестен, поэтому я произвольно выбрал 1 миллион строк. Я хочу вернуть индекс каждого столбца, в котором сумма строк соответствует указанному условию, ie. = 0.

Очевидно, на выполнение этого нужно ГОДЫ. Я не уверен, можно ли использовать распараллеливание для этого l oop или какие другие методы я могу использовать для увеличения скорости. Как я уже сказал, я могу работать в Azure с большим количеством ядер и / или большего количества памяти, если это позволит.

Есть ли лучший / более быстрый способ сделать это?

1 Ответ

0 голосов
/ 26 мая 2020

Я не думаю, что можно запустить эту программу в разумные сроки, поскольку 26 ^ 16 равно 43,608,742,899,428,874,059,776. Я думаю, что есть гораздо более быстрое решение этой проблемы с использованием динамического c программирования с состояниями dp [SUM] [letterIndex]. Вы можете предварительно вычислить, сколько комбинаций букв существует с суммой, равной SUM с использованием букв letterIndex. Сложность этого решения составляет O (26 * 16 * MAX), где MAX - максимальное значение в ваших векторах. Конечно, это верно, если числа в векторах являются целыми числами.

...