Skip to content

Commit 91eb0de

Browse files
author
Sandeep Mittal
committed
adding copod skewness and updating unit tests
1 parent 18312d6 commit 91eb0de

5 files changed

Lines changed: 71 additions & 43 deletions

File tree

include/chimbuko/ad/ADOutlier.hpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ namespace chimbuko {
238238

239239
private:
240240
double m_alpha; /**< Used to prevent log2 overflow */
241-
double m_threshold; /**< Threshold used to filter anomalies in HBOS*/
241+
double m_threshold; /**< Threshold used to filter anomalies in COPOD*/
242242
bool m_use_global_threshold; /**< Flag to use global threshold*/
243243
//double m_threshold; /** sync with global threshold */
244244
OutlierStatistic m_statistic; /** Which statistic to use for outlier detection */
@@ -253,13 +253,13 @@ namespace chimbuko {
253253
public:
254254

255255
/**
256-
* @brief Construct a new ADOutlierHBOS object
256+
* @brief Construct a new ADOutlierCOPOD object
257257
*
258258
*/
259259
ADOutlierCOPOD(OutlierStatistic stat = ExclusiveRuntime, double threshold = 0.99, bool use_global_threshold = true);
260260

261261
/**
262-
* @brief Destroy the ADOutlierHBOS object
262+
* @brief Destroy the ADOutlierCOPOD object
263263
*
264264
*/
265265
~ADOutlierCOPOD();
@@ -308,11 +308,12 @@ namespace chimbuko {
308308

309309
private:
310310
double m_alpha; /**< Used to prevent log2 overflow */
311-
double m_threshold; /**< Threshold used to filter anomalies in HBOS*/
311+
double m_threshold; /**< Threshold used to filter anomalies in COPOD*/
312312
bool m_use_global_threshold; /**< Flag to use global threshold*/
313-
//double m_threshold; /** sync with global threshold */
314-
OutlierStatistic m_statistic; /** Which statistic to use for outlier detection */
313+
//double m_threshold; /**< sync with global threshold */
314+
OutlierStatistic m_statistic; /**< Which statistic to use for outlier detection */
315315

316+
std::unordered_map<unsigned long, int> m_skewness; /**< skewness for each function*/
316317
};
317318

318319

src/ad/ADOutlier.cpp

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,24 @@ Anomalies ADOutlierCOPOD::run(int step) {
571571
recoverable_error(std::string("AD: Zero function runtimes "));
572572
continue;
573573
}
574+
verboseStream << "Size of runtimes: " << runtimes.size() << ", func_id: " << func_id << std::endl;
575+
576+
//calculate skewness of runtimes for func_id
577+
const double mu = std::accumulate(runtimes.begin(), runtimes.end(), 0.0) / runtimes.size();
578+
579+
std::vector<double> diff = std::vector<double>(runtimes.size());
580+
std::transform(runtimes.begin(), runtimes.end(), diff.begin(), [mu](double x) {return x - mu;});
581+
const double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0);
582+
const double stdev = std::sqrt(sq_sum / runtimes.size());
583+
584+
double summ = 0;
585+
for (int i=0; i<runtimes.size(); i++) {
586+
summ += std::pow((runtimes.at(i) - mu), 3);
587+
}
588+
589+
const double abs_skewness = summ / ((runtimes.size() - 1) * std::pow(stdev,3));
590+
m_skewness[func_id] = (abs_skewness < 0) ? -1 : (abs_skewness > 0) ? 1 : 0;
591+
574592
}
575593

576594
//Update temp runstats to include information collected previously (synchronizes with the parameter server if connected)
@@ -637,34 +655,44 @@ unsigned long ADOutlierCOPOD::compute_outliers(Anomalies &outliers,
637655
verboseStream << "Size of empiricalCDF(recon_n_runtimes): " << func_n_ecdf.size() << std::endl;
638656

639657
std::vector<double> mean_pn_ecdf = std::vector<double>(func_p_ecdf.size(), 0.0);
640-
verboseStream << "Size of mean_pn_ecdf: " << mean_pn_ecdf.size() << std::endl;
658+
verboseStream << "Size of mean_pn_ecdf: " << mean_pn_ecdf.size() << ", func_id: " << func_id << std::endl;
641659

642660
for(int i=0; i < mean_pn_ecdf.size(); i++){
643661
mean_pn_ecdf.at(i) = (func_p_ecdf.at(i) + func_n_ecdf.at(i)) / 2.0;
644662
verboseStream << "mean_pn_ecdf.at(i): " << mean_pn_ecdf.at(i) << ", func_p_ecdf.at(i): " << func_p_ecdf.at(i) << ", func_n_ecdf.at(i): " << func_n_ecdf.at(i) << std::endl;
645663
}
646664

665+
//use skewness
666+
std::vector<double> skewness_arr = std::vector<double>(func_p_ecdf.size(), 0.0);
667+
const int p_sign = (m_skewness[func_id] - 1) < 0 ? -1 : (m_skewness[func_id] - 1) > 0 ? 1 : 0;
668+
const int n_sign = (m_skewness[func_id] + 1) < 0 ? -1 : (m_skewness[func_id] + 1) > 0 ? 1 : 0;
669+
670+
for (int i = 0; i< func_p_ecdf.size(); i++) {
671+
skewness_arr.at(i) = (func_p_ecdf.at(i) * -1 * p_sign) + (func_n_ecdf.at(i) * n_sign);
672+
verboseStream << "skewness_arr.at(" << i << "): " << skewness_arr.at(i) << std::endl;
673+
}
674+
675+
std::vector<double> final_comp = std::vector<double>(skewness_arr.size(), 0.0);
676+
for (int i = 0; i < skewness_arr.size(); i++) {
677+
final_comp.at(i) = std::max(skewness_arr.at(i), mean_pn_ecdf.at(i));
678+
}
647679

648-
//for(int i=0; i < param[func_id].counts().size(); i++){
649-
// int count = param[func_id].counts().at(i);
650-
// double p = count / tot_runtimes;
651-
// prob_counts.at(i) += p;
652-
//}
653680

654-
for(int i=0; i<mean_pn_ecdf.size(); i++)
655-
verboseStream << "mean_pn_ecdf at " << i << ": " << mean_pn_ecdf.at(i) << std::endl;
681+
//for(int i=0; i<mean_pn_ecdf.size(); i++)
682+
// verboseStream << "mean_pn_ecdf at " << i << ": " << mean_pn_ecdf.at(i) << std::endl;
656683

657684
//Create COPOD score vector
658-
std::vector<double> out_scores_i = std::vector<double>(mean_pn_ecdf.size(), 0.0);
685+
std::vector<double> out_scores_i = std::vector<double>(final_comp.size(), 0.0);
659686
verboseStream << "m_alpha: " << m_alpha << std::endl;
660687

661688
double min_score = -1 * log2(0.0 + m_alpha);
662-
double max_score = -1 * log2(1.0 + m_alpha);
689+
double max_score = log2(1.0 + m_alpha) - min_score;
690+
verboseStream << "Initializaing min_score: " << min_score << ", max_score: " << max_score <<std::endl;
663691
verboseStream << "out_scores_i: " << std::endl;
664-
for(int i=0; i < mean_pn_ecdf.size(); i++){
665-
double l = -1 * log2(mean_pn_ecdf.at(i) + m_alpha);
692+
for(int i=0; i < final_comp.size(); i++){
693+
double l = -1 * log2(final_comp.at(i) + m_alpha);
666694
out_scores_i.at(i) = l;
667-
verboseStream << "Mean_ecdf at " << i << ": " << mean_pn_ecdf.at(i) << ", score: "<< l << std::endl;
695+
verboseStream << "Final_comp at " << i << ": " << final_comp.at(i) << ", score: "<< l << std::endl;
668696
//if(prob_counts.at(i) > 0) {
669697
if(l < min_score){
670698
min_score = l;
@@ -683,9 +711,10 @@ unsigned long ADOutlierCOPOD::compute_outliers(Anomalies &outliers,
683711

684712
//compute threshold
685713
verboseStream << "Global threshold before comparison with local threshold = " << param[func_id].get_threshold() << std::endl;
686-
double l_threshold = min_score + (m_threshold * (max_score - min_score));
714+
double l_threshold = (max_score < 0) ? (-1 * m_threshold * (max_score - min_score)) : min_score + (m_threshold * (max_score - min_score));
715+
verboseStream << "l_threshold computed: " << l_threshold << std::endl;
687716
if(m_use_global_threshold) {
688-
if(l_threshold < param[func_id].get_threshold()) {
717+
if(l_threshold < param[func_id].get_threshold() && param[func_id].get_threshold() > (-1 * log2(1.00001))) {
689718
l_threshold = param[func_id].get_threshold();
690719
} else {
691720
param[func_id].set_glob_threshold(l_threshold); //.get_histogram().glob_threshold = l_threshold;
@@ -694,31 +723,29 @@ unsigned long ADOutlierCOPOD::compute_outliers(Anomalies &outliers,
694723
}
695724

696725
//Compute COPOD based score for each datapoint
697-
//const double bin_width = param[func_id].bin_edges().at(1) - param[func_id].bin_edges().at(0);
698-
//const int num_bins = param[func_id].counts().size();
699-
//verboseStream << "Bin width: " << bin_width << std::endl;
700726

701727
int top_out = 0;
702-
//int running_idx = 0;
728+
int running_idx = 0;
703729
for (auto itt : data) {
704730
if (itt->get_label() == 0) {
705731

706732
const double runtime_i = this->getStatisticValue(*itt); //runtimes.push_back(this->getStatisticValue(*itt));
707733
double ad_score;
708-
int running_idx = 0;
709-
710-
//find bin index of data(runtime_i) in merged histogram
711-
for (int i=1; i < param[func_id].bin_edges().size(); i++) {
712-
if (runtime_i < param[func_id].bin_edges().at(i)) {
713-
running_idx = i-1;
714-
break;
715-
}
734+
735+
if (running_idx < final_comp.size()) {
736+
verboseStream << "final_comp.at(" << running_idx << "): " << final_comp.at(running_idx) << ", func_id: " << func_id << ", runtime: " << runtime_i << std::endl;
737+
738+
if (out_scores_i.at(running_idx) > l_threshold) //(final_comp.at(running_idx) > 0) // < 0.9)
739+
ad_score = l_threshold + 1;
740+
else
741+
ad_score = l_threshold - 1;
742+
743+
running_idx++;
744+
}
745+
else {
746+
recoverable_error("AD: COPOD: runtime Index");
747+
continue;
716748
}
717-
verboseStream << "mean_pn_ecdf.at(running_idx): " << mean_pn_ecdf.at(running_idx) << std::endl;
718-
if (mean_pn_ecdf.at(running_idx) < 0.99)
719-
ad_score = l_threshold + 1;
720-
else
721-
ad_score = l_threshold - 1;
722749

723750
itt->set_outlier_score(ad_score);
724751
verboseStream << "ad_score: " << ad_score << ", l_threshold: " << l_threshold << std::endl;

test/unit_tests/ad/COPODOutlierADs.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class ADOutlierCOPODTest: public ADOutlierCOPOD{
2828
};
2929

3030

31-
TEST(HBOSADOutlierTestSyncParamWithPSComputeOutliers, Works){
31+
TEST(COPODADOutlierTestSyncParamWithPSComputeOutliers, Works){
3232
CopodParam global_params_ps; //parameters held in the parameter server
3333
CopodParam local_params_ad, local_params_ad2; //parameters collected by AD
3434

@@ -49,7 +49,7 @@ TEST(HBOSADOutlierTestSyncParamWithPSComputeOutliers, Works){
4949
std::vector<double> runtimes;
5050
Histogram &r = local_params_ad[0];
5151
for(int i=0;i<N;i++) {
52-
double val = i==N-1 ? 1000 : double(dist(gen));
52+
double val = i==N-1 ? 10000 : double(dist(gen));
5353
call_list.push_back( createFuncExecData_t(0,0,0, 0, "my_func", 1000*(i+1), val) );
5454
runtimes.push_back(val);
5555
std::cout << "vals in localhist 1: " << val << std::endl;
@@ -65,7 +65,7 @@ TEST(HBOSADOutlierTestSyncParamWithPSComputeOutliers, Works){
6565
std::vector<double> runtimes;
6666
Histogram &r = local_params_ad2[0];
6767
for(int i=0;i<N;i++) {
68-
double val = i==N-1 ? 1000 : double(dist(gen));
68+
double val = i==N-1 ? 20000 : double(dist(gen));
6969
call_list2.push_back( createFuncExecData_t(0,0,0, 0, "my_func", 1000*(i+1), val) );
7070
runtimes.push_back(val);
7171
std::cout << "vals in localhist 2: " << val << std::endl;

test/unit_tests/ad/HBOSOutlierTestBPFile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ TEST(HBOSADOutlierBPFileWithoutPServer, Works) {
115115
//Parameters for the connection to the instrumented binary trace output
116116
params.trace_engineType = "BPFile"; // BPFile or SST
117117
params.trace_data_dir = trace_data_dir; // *.bp location
118-
std::string bp_prefix = "tau-metrics-xgc-es-cpp-gpu"; //"tau-metrics"; // bp file prefix (e.g. tau-metrics-[nwchem])
118+
std::string bp_prefix = "tau-metrics"; //"tau-metrics-xgc-es-cpp-gpu"; // bp file prefix (e.g. tau-metrics-[nwchem])
119119

120120
//The remainder are optional arguments. Enable using the appropriate command line switch
121121
params.program_idx = 0;

test/unit_tests/ad/SSTDOutlierTestBPFile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ TEST(SSTDADOutlierBPFileWithoutPServer, Works) {
116116
//Parameters for the connection to the instrumented binary trace output
117117
params.trace_engineType = "BPFile"; // argv[1]; // BPFile or SST
118118
params.trace_data_dir = trace_data_dir; // *.bp location
119-
std::string bp_prefix = "tau-metrics-xgc-es-cpp-gpu"; //"tau-metrics"; //argv[3]; // bp file prefix (e.g. tau-metrics-[nwchem])
119+
std::string bp_prefix = "tau-metrics"; //"tau-metrics-xgc-es-cpp-gpu"; //argv[3]; // bp file prefix (e.g. tau-metrics-[nwchem])
120120

121121
//The remainder are optional arguments. Enable using the appropriate command line switch
122122
params.program_idx = 0;

0 commit comments

Comments
 (0)