2018 оны 2 сарын 5

R дээрх зэрэгцээ тооцоолол болон C++ код

Статистикийн R хэл буюу R програм дээр их өгөгдөлтэй ажиллахдаа явуулсан зэрэгцээ тооцоолол болон C++ код хольж бичин ажиллуулсаны эцэст гарсан зарим дүгнэлт

ЭШ-ний ажлын хүрээнд их өгөгдөлтэй (big data) ажиллах болсон бөгөөд үүнд R хэлийг ашигласан юм. Ажлын гол цөм нь оптимизацын нэг алгоритм байсан ба түүнийг бүрэн програмчлах шаардлага тулгарсан. Ингээд програмчлахдаа өндөр түвшинд эзэмшсэн R хэлээ ашиглалаа. Тооцоонд хэдэн мянган итерац ажиллах тул зэрэгцээ тооцоолол (parallel computing) зайлшгүй шаардлагатай болсон. Гэвч өгөгдлийн хэмжээ их тул зэрэгцээ тооцооллын олон кластер ажиллуулахад түвэгтэй болсон. Хэрэв олон кластер ажиллуулна гэвэл өгөгдлөө санах ойд бага зай эзлэх өөр бүтэц структурт шилжүүлж ашиглах шаардлагатай байсан. Гэвч санах ойд хэмнэлттэй тэрхүү бүтэцтэй өгөгдлийг боловсруулахад ашиглаж болох for давталтын оператор R дээр тун чиг удаан ажилладаг юм. Тиймдээ ч apply(), replicate() зэрэг функц байдаг юм л даа. Мөн давталт зэрэг R дээр удаан хэрэгждэг үйлдлүүдийг C++ хэлний код оруулж ирэх замаар хурдлуулж болдог тухай цаашилбал хэдэн зуу дахин илүү хурдан ажилласан тухай мэдээ баримт интернэтээр дүүрэн байдаг. Иймд өөр бусад арга замыг түр хойш тавиад энэ замаар оров оо.

Ингээд боловсруулсан алгоритм, бичсэн кодоо шалгах болон жинхэнэ өгөгдөл дээрээ ажиллуулах зэргээр их бага янз бүрийн өгөгдөл дээр ажиллуулж үзсэн. Өөрөөр хэлбэл зэрэгцээ тооцоолол болон C++ код ашиглах зэргийг тал бүрээс нь туршин ажиллуулсан гэсэн үг. Үүний дүнд R дээр C++ код бичиж ажилуулах (Rcpp багц ашигласан) нь хүн болгоны хэлдэг, бичдэг шиг үргэлж ашигтай байдаггүй болохыг тодорхой харлаа. Уг нь дараах энгийн кодыг л ажиллуулах гэсэн юм.

Rcpp::cppFunction('double penaltyCPP(NumericVector chro, int chrolen, NumericMatrix sparseadjmat) {
  int penalty = 0;
  int nrow = sparseadjmat.nrow();
  for (int i = 0; i < chrolen - 1; i++) {
    for (int j = i + 1; j < chrolen; j++) {
      if (chro(i) + chro(j) > 1) {
        bool exists = false;
        for (int n = 0; n < nrow; n++) {
          if (sparseadjmat(n,0) == i + 1 && sparseadjmat(n,1) == j + 1) {
            exists = true;
            break;
          }
        }
        if (!exists) {
          penalty++;
        }
      }
    }
  }
  return penalty;
}')

Харин зэрэгцээ тооцооллын хувьд олон хүчин зүйл нөлөөлдөг болохоор ганц өгүүлбэрээр шууд эцэслэн дүгнэх боломжгүй юм. Ямартаа ч зэрэгцээ тооцоолол бүхэн ердийн тооцооллоос дандаа хурдан ажиллана гэж байхгүй. Зэрэгцээ тооцоолол явуулах нь миний нэг багшийн хэлдэгчлэн "бөөсөнд хутга гаргах" гэдэг шиг нүсэрдэх тохиолдол байдаг.

За ингээд R дотор C++ код хольж бичиж ашиглах нь үргэлж ашигтай биш болохыг анхаарч байгаарай. Ахисан түвшний програмчлалын энэхүү асуудлын тухай дэлгэрэнгүй, тодорхой зүйлсийг Статистик програмчлалын R хэл номынхоо хоёр дахь хэвлэлтэд тусгах болно.

Эцэст нь өөртөө тулгарсан асуудлаа шийдэж чадсан уу гэж сонирхон уншиж байгаа бол хариулъя. Мэдээж чадсан. Зэрэгцээ тооцоолол асуудалгүй ажиллаж байгаа. Бас санах ойн хэрэглээг ч багасгаж чадсан. Rcpp ашиглаад бүтээгүй асуудлыг R хэлний үндсэн багцуудад байдаг функцээр хөнгөхөн шийдсэн.