Skip to content

Commit 9d4507a

Browse files
committed
To ADsim, added the ability to apply an AD algorithm to the input trace data rather than user tagging
Added an ADsim example using a real AD algorithm and the ADsim API ADsim event indices now use start step rather than end step in id
1 parent 6d1b6d2 commit 9d4507a

10 files changed

Lines changed: 259 additions & 36 deletions

File tree

sim/include/sim/ad.hpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include<chimbuko/ad/ADNormalEventProvenance.hpp>
66
#include<chimbuko/ad/ADEvent.hpp>
77
#include<chimbuko/ad/ADCounter.hpp>
8+
#include<chimbuko/ad/ADOutlier.hpp>
89
#include<map>
910

1011
namespace chimbuko_sim{
@@ -17,6 +18,7 @@ namespace chimbuko_sim{
1718
std::unordered_map<unsigned long, std::list<ExecData_t> > m_all_execs; /**< Map of thread to execs */
1819
std::unordered_map<eventID, CallListIterator_t> m_eventid_map; /**< Map from event index to iterator */
1920
std::map<unsigned long, std::list<CallListIterator_t> > m_step_execs; /**< Events in any given step */
21+
std::map<unsigned long, unsigned long> m_entry_step_count; /**< Count of events starting on a given step (used to assign event indices) */
2022

2123
unsigned long m_largest_step; /**< Largest step index of an inserted function execution thus far encountered */
2224
unsigned long m_program_start;
@@ -28,6 +30,8 @@ namespace chimbuko_sim{
2830
ADNormalEventProvenance m_normal_events;
2931
ADMetadataParser m_metadata;
3032
std::unique_ptr<ADProvenanceDBclient> m_pdb_client;
33+
ADLocalNetClient m_net_client; /**< The local net client. Only activated if an AD algorithm is used */
34+
ADOutlier* m_outlier; /**< The local outlier algorithm instance, if used*/
3135
public:
3236
/**
3337
* @brief Initialize the AD simulator
@@ -50,7 +54,18 @@ namespace chimbuko_sim{
5054
ADsim(int window_size, int pid, int rid, unsigned long program_start, unsigned long step_freq): ADsim(){
5155
init(window_size, pid, rid, program_start, step_freq);
5256
}
53-
ADsim(){}
57+
ADsim(): m_outlier(nullptr){}
58+
59+
ADsim(ADsim &&r);
60+
61+
~ADsim(){ if(m_outlier) delete m_outlier; }
62+
63+
/**
64+
* @brief Set up the AD algorithm. Parameters correspond to those in ADOutlier::set_algorithm
65+
*
66+
* Using an AD algorithm to analyze the data is optional. Set the ad_algorithm() string to a value other than "none" to switch the algorithm
67+
*/
68+
void setupADalgorithm(const double hbos_thres, const bool glob_thres, const double sstd_sigma, ADOutlier::OutlierStatistic stat = ADOutlier::ExclusiveRuntime);
5469

5570
ADProvenanceDBclient &getProvDBclient(){ return *m_pdb_client; }
5671

@@ -69,7 +84,7 @@ namespace chimbuko_sim{
6984
const std::string &func_name,
7085
unsigned long start,
7186
unsigned long runtime,
72-
bool is_anomaly,
87+
bool is_anomaly = false,
7388
double outlier_score = 0.);
7489

7590
/**

sim/include/sim/ad_params.hpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,42 @@
11
#include<chimbuko/param/sstd_param.hpp>
2+
#include<chimbuko/ad/ADOutlier.hpp>
23
#include "id_map.hpp"
34

45
namespace chimbuko_sim{
56
using namespace chimbuko;
67

8+
struct ADalgParams{
9+
std::string algorithm;
10+
double hbos_thres;
11+
bool glob_thres;
12+
double sstd_sigma;
13+
ADOutlier::OutlierStatistic stat;
14+
15+
ADalgParams(const std::string &algorithm, double hbos_thres, bool glob_thres, double sstd_sigma, ADOutlier::OutlierStatistic stat): algorithm(algorithm), hbos_thres(hbos_thres), glob_thres(glob_thres), sstd_sigma(sstd_sigma), stat(stat){}
16+
17+
/**
18+
* @brief Default parameters
19+
*/
20+
ADalgParams(): algorithm("none"), hbos_thres(0.99), glob_thres(true), sstd_sigma(12.0), stat(ADOutlier::ExclusiveRuntime){}
21+
};
22+
23+
/**
24+
* @brief Set the parameters of the ad algorithm
25+
*
26+
* If algorithm=="none" (defulat) the user is expected to tag events manually (the params put in the provDB will use the SSTD algorithm format), otherwise it will use one of Chimbuko's algorithms
27+
*/
28+
inline ADalgParams & adAlgorithmParams(){ static ADalgParams alg; return alg; }
29+
30+
31+
/**
32+
* @brief If an AD algorithm is not used (ad_algorithm() == "none" [default]) this is the object containing the params that are placed in the provDB
33+
*/
734
inline SstdParam & globalParams(){ static SstdParam p; return p; }
835

9-
//"register" a function, generating fake statistics given a provided mean and standard deviation
36+
/**
37+
* @brief If an AD algorithm is not used (ad_algorithm() == "none" [default]) all functions should be 'registered' using this command
38+
*
39+
* This function sets up both the function idx map and enters the provided statistics in the globalParams() instance
40+
*/
1041
void registerFunc(const std::string &func_name, unsigned long mean_runtime, unsigned long std_dev_runtime, int seen_count);
1142
};

sim/include/sim/id_map.hpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,22 @@
44
#include<unordered_map>
55

66
namespace chimbuko_sim{
7-
//All functions must be registered
7+
/**
8+
* @brief Map of function name to index
9+
*/
810
std::unordered_map<std::string, unsigned long> & funcIdxMap();
911

10-
//Automatically register counter names with indices
12+
/**
13+
* @brief Register a function (set up the function idx map)
14+
* @param func_name The function name
15+
* @return The assigned function index
16+
*/
17+
unsigned long registerFunc(const std::string &func_name);
18+
19+
20+
/**
21+
* @brief A class to automatically register counter names with indices
22+
*/
1123
class CounterIdxManager{
1224
std::unordered_map<std::string, unsigned long> cid_map;
1325
std::unordered_map<int, std::string> cname_map;
@@ -21,5 +33,8 @@ namespace chimbuko_sim{
2133
const std::unordered_map<int, std::string>* getCounterMap(){ return &cname_map; }
2234
};
2335

36+
/**
37+
* @brief Get the global shared instance of the counter index manager
38+
*/
2439
inline CounterIdxManager & getCidxManager(){ static CounterIdxManager cman; return cman; }
2540
};

sim/include/sim/pserver.hpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include<chimbuko/param.hpp>
34
#include<chimbuko/pserver/global_anomaly_stats.hpp>
45
#include<chimbuko/pserver/global_counter_stats.hpp>
56

@@ -12,23 +13,40 @@ namespace chimbuko_sim{
1213
GlobalCounterStats global_counter_stats; //global counter statistics
1314
PSstatSenderGlobalAnomalyStatsPayload anomaly_stats_payload;
1415
PSstatSenderGlobalCounterStatsPayload counter_stats_payload;
16+
LocalNet m_net; /**< The net server */
17+
ParamInterface* m_ad_params; /**< If using an AD algorithm to analyze the trace, these are the global parameters*/
1518
public:
19+
20+
/**
21+
* @brief Construct the pserver. To use an AD algorithm, the static function ad_algorithm should be changed *before* constructing the pserver
22+
*/
23+
pserverSim();
1624

17-
pserverSim(): anomaly_stats_payload(&global_func_stats), counter_stats_payload(&global_counter_stats){}
25+
~pserverSim();
1826

19-
//Stand-in for the func statistics comms from AD -> pserver
27+
/**
28+
* @brief Stand-in for the func statistics comms from AD -> pserver
29+
*/
2030
void addAnomalyData(const ADLocalFuncStatistics &loc){
2131
global_func_stats.add_anomaly_data(loc);
2232
}
33+
34+
/**
35+
* @brief Stand-in for the counter statistics comms from AD -> pserver
36+
*/
2337
void addCounterData(const ADLocalCounterStatistics &loc){
2438
global_counter_stats.add_counter_data(loc);
2539
}
26-
27-
//Mirror write functionality of PSstatSender
40+
41+
/**
42+
* @brief Mirror write functionality of PSstatSender
43+
*/
2844
void writeStreamingOutput() const;
2945
};
3046

31-
47+
/**
48+
* @brief Get the shared pserver instance
49+
*/
3250
inline pserverSim & getPserver(){ static pserverSim ps; return ps; }
3351

3452
};

sim/main/Makefile.am

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/3rdparty -I$(top_srcdir)/s
22
LDADD = ../src/libchimbuko_sim.la ../../src/libchimbuko.la -lstdc++fs
33

44
simmaindir = $(prefix)/sim/main
5-
simmain_PROGRAMS = example1
5+
simmain_PROGRAMS = example1 example2
66

77
example1_SOURCES = example1.cpp
88
example1_LDADD = $(LDADD)
9+
10+
example2_SOURCES = example2.cpp
11+
example2_LDADD = $(LDADD)

sim/main/example2.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//This example demonstrates the simulator using the ADSim API directly, and using a real outlier algorithm
2+
#include<mpi.h>
3+
#include<sim.hpp>
4+
#include<random>
5+
6+
using namespace chimbuko_sim;
7+
8+
int main(int argc, char **argv){
9+
MPI_Init(&argc, &argv);
10+
11+
int window_size = 5; //number of events to record around an anomaly in the provenance data
12+
int pid = 0; //program index
13+
unsigned long program_start = 100;
14+
unsigned long step_freq = 1000;
15+
16+
//Set the AD algorithm *before instantiating the simulator!
17+
ADalgParams & alg = adAlgorithmParams();
18+
alg.algorithm = "sstd";
19+
alg.sstd_sigma = 12.0;
20+
21+
//Setup the "AD" instances
22+
int n_ranks = 1;
23+
std::vector<ADsim> ad;
24+
for(int r=0;r<n_ranks;r++)
25+
ad.push_back(ADsim(window_size, pid, r, program_start, step_freq));
26+
27+
//Setup some functions
28+
registerFunc("main");
29+
registerFunc("child");
30+
31+
//Setup some systems
32+
std::vector<int> cpu_threads(4); for(int i=0;i<4;i++) cpu_threads[i] = i;
33+
34+
int gpus = 2;
35+
std::vector<int> gpu_threads(gpus); //assign virtual thread indices to gpus and register
36+
for(int g=0;g<gpus;g++){
37+
gpu_threads[g] = cpu_threads.size() + g; //GPU virtual index should not correspond with a CPU core thread index
38+
ad[0].registerGPUthread(gpu_threads[g]);
39+
}
40+
41+
std::default_random_engine gen;
42+
std::normal_distribution<double> dist(100,20); //normal std.dev = 20
43+
44+
unsigned long child_start = 200;
45+
int nexec = 500;
46+
std::vector<int> starts(nexec);
47+
std::vector<int> runtimes(nexec);
48+
for(int i=0;i<nexec;i++){
49+
if(i==0) starts[i] = child_start;
50+
else starts[i] = starts[i-1] + runtimes[i-1] + 1;
51+
runtimes[i] = int( dist(gen) );
52+
}
53+
//Add an anomaly
54+
starts.push_back( starts.back() + runtimes.back() + 1 );
55+
runtimes.push_back( 400 );
56+
nexec++;
57+
58+
int program_end = starts.back() + runtimes.back() + 50;
59+
60+
auto main = ad[0].addExec(0, "main", program_start, program_end - program_start);
61+
for(int i=0;i<nexec;i++){
62+
CallListIterator_t child = ad[0].addExec(0, "child", starts[i], runtimes[i]);
63+
ad[0].bindParentChild(main, child);
64+
}
65+
66+
//Run the simulation
67+
int nstep = ad[0].largest_step() + 1;
68+
std::cout << "Got data for " << nstep << " steps" << std::endl;
69+
70+
for(int i=0;i<nstep;i++){
71+
std::cout << "Step " << i << " contains " << ad[0].nStepExecs(i) << " execs" << std::endl;
72+
ad[0].step(i);
73+
}
74+
75+
MPI_Finalize();
76+
return 0;
77+
}

0 commit comments

Comments
 (0)