Skip to content

Commit

Permalink
Merge pull request cms-sw#200 from kmcdermo/stress-test
Browse files Browse the repository at this point in the history
Stress test scripts
  • Loading branch information
dan131riley committed Feb 28, 2019
2 parents 1b6e3d0 + 0c73ea9 commit 1da2566
Show file tree
Hide file tree
Showing 4 changed files with 555 additions and 0 deletions.
20 changes: 20 additions & 0 deletions plotting/makeStressPlot.sh
@@ -0,0 +1,20 @@
#!/bin/bash

## Command line config
infile_name=${1:-"stress_test_SKL-SP_results.txt"}
graph_label=${2:-"[Turbo=OFF(Long)]"}
outfile_name=${3:-"noturbo1_long.pdf"}

## reduce stress test results to results used in macro only
tmp_infile_name="tmp_results.txt"
> "${tmp_infile_name}"

grep "SSE3" "${infile_name}" >> "${tmp_infile_name}"
grep "AVX2" "${infile_name}" >> "${tmp_infile_name}"
grep "AVX512" "${infile_name}" >> "${tmp_infile_name}"

## Run little macro
root -l -b -q plotting/plotStress.C\(\"${tmp_infile_name}\",\"${graph_label}\",\"${outfile_name}\"\)

## remove tmp file
rm "${tmp_infile_name}"
170 changes: 170 additions & 0 deletions plotting/plotStress.C
@@ -0,0 +1,170 @@
#include "TString.h"
#include "TColor.h"
#include "TStyle.h"
#include "TGraph.h"
#include "TLegend.h"
#include "TCanvas.h"

#include <iostream>
#include <vector>

///////////////////////
// Structs for macro //
///////////////////////

struct setStruct
{
setStruct () {}
setStruct (const TString & label, const Double_t x)
: label(label), x(x) {}

TString label;
UInt_t x;
};

struct xyStruct
{
xyStruct () {}
xyStruct (const Double_t x, const Double_t y)
: x(x), y(y) {}

Double_t x;
Double_t y;
};

struct testStruct
{
testStruct () {}
testStruct (const TString & label, const Color_t color)
: label(label), color(color) {}

TString label;
Color_t color;

std::vector<xyStruct> xyPoints;
TGraph * graph;
};

////////////////
// Main Macro //
////////////////

void plotStress(const TString & infile_name, const TString & graph_label, const TString & outfile_name)
{
// no stats boxes
gStyle->SetOptStat(0);

// which tests to plot
std::vector<testStruct> tests = {
{"nTH1_nEV1",kBlue},
{"nTH16_nEV16",kRed+1},
{"nTH32_nEV16",kGreen+1},
{"nTH32_nEV32",kMagenta},
{"nTH64_nEV32",kOrange+1},
{"nTH64_nEV64",kBlack},
{"nJOB32",kViolet-1},
{"nJOB64",kAzure+10}
};

// which instruction sets (nVU) to use
std::vector<setStruct> sets = {
{"SSE3",4},
{"AVX2",8},
{"AVX512",16}
};

// make label for x-axis
const auto nset = sets.size();
TString set_label;
for (auto iset = 0U; iset < nset; iset++)
{
const auto & set = sets[iset];
set_label += Form(" %s (x=%i)%s",set.label.Data(),set.x,(iset+1!=nset?",":""));
}

// read input file, fill testStruct vector
std::ifstream input(infile_name.Data(),std::ios::in);
TString test_set_label;
Double_t y;

// hacky read-in, but sufficient for small number of tests
while (input >> test_set_label >> y)
{
for (auto & test : tests)
{
if (test_set_label.Contains(test.label))
{
for (const auto & set : sets)
{
if (test_set_label.Contains(set.label))
{
test.xyPoints.emplace_back(set.x,y);
break;
} // end check over input label contains given instruction set label
} // end loop over instruction set labels
} // end check over input label contains given test label
} // end loop over instruction test labels
} // end loop over reading input file

// setup canvas
auto canv = new TCanvas();
canv->cd();
canv->SetTickx(1);
canv->SetTicky(1);
canv->SetGridy(1);

// setup legend
auto leg = new TLegend(0.77,0.8,0.99,0.99);
leg->SetNColumns(2);

// loop tests, fill graphs, add to canvas + legend
for (auto itest = 0U; itest < tests.size(); itest++)
{
// get test result
auto & test = tests[itest];

// get test info (points, label, color, graph)
const auto & xyPoints = test.xyPoints;
const auto & label = test.label;
const auto color = test.color;
auto & graph = test.graph;

// make new graph, set style
graph = new TGraph(test.xyPoints.size());
graph->SetTitle("Time vs ISA Ext "+graph_label);
graph->SetLineColor(color);
graph->SetMarkerColor(color);
graph->SetMarkerStyle(kFullCircle);
graph->SetMarkerSize(1);

// add graph points
for (auto ixyPoint = 0U; ixyPoint < xyPoints.size(); ixyPoint++)
{
const auto & xyPoint = xyPoints[ixyPoint];
graph->SetPoint(ixyPoint,xyPoint.x,xyPoint.y);
}

// draw graph
graph->Draw(itest>0?"CP SAME":"ACP");

// graphs can only set x-y axis info after being drawn
graph->GetXaxis()->SetRangeUser(0,20);
graph->GetYaxis()->SetRangeUser(0,0.2);
graph->GetXaxis()->SetTitle("Floats in 1 vector [ISA Extensions: "+set_label+"]");
graph->GetYaxis()->SetTitle("Time / evt / physical core [s]");

// add graph to leg
leg->AddEntry(graph,label.Data(),"lp");
}

// draw leg
leg->Draw("same");

// save it
canv->SaveAs(outfile_name.Data());

// delete it all
for (auto & test : tests) delete test.graph;
delete leg;
delete canv;
}
144 changes: 144 additions & 0 deletions xeon_scripts/stress-test-common.sh
@@ -0,0 +1,144 @@
#!/bin/bash

##########################
## Global Configuration ##
##########################

## Instruction sets defined with "make" command line settings
export SSE3="CPPUSERFLAGS+=\"-march=core2\" CXXUSERFLAGS+=\"-march=core2\" VEC_GCC=\"-march=core2\" VEC_ICC=\"-march=core2\""
export AVX=""
export AVX2="AVX2:=1"
export AVX512="AVX_512:=1"

## Output options
export tmp_ext="log"
export ext="txt"

## Tmp output labels
export nth_label="nTH"
export nev_label="nEV"
export njob_label="nJOB"
export ncore_label="nCORE"
export nproc_label="nPROC"
export nloop_label="nLOOP"

######################
## N Physical Cores ##
######################

function GetNCore ()
{
local nth=${1}
local maxcore=${2}

if (( ${nth} <= ${maxcore} ))
then
local ncore="${nth}"
else
local ncore="${maxcore}"
fi

echo "${ncore}"
}
export -f GetNCore

####################
## Core Test Loop ##
####################

function MkFitLoop ()
{
local min_duration=${1}
local test_exe=${2}
local nproc=${3}
local njob=${4}

local start_time=$( date +"%s" )
local end_time=$(( ${start_time} + ${min_duration} ))

## compute number of events to process per job
local nproc_per_job=$(( ${nproc} / ${njob} ))

## global variable to be read back in main loop to keep track of number of times processed
nloop=0

## run stress test for min min_duration with an emulated do-while loop: https://stackoverflow.com/a/16491478
while

## launch jobs in parallel to background : let scheduler put jobs all around
for (( ijob = 0 ; ijob < ${njob} ; ijob++ ))
do
## want each mkFit job to process different events, so compute an offset
local start_event=$(( ${nproc_per_job} * ${ijob} ))

## run the executable
${test_exe} --num-events ${nproc_per_job} --start-event ${start_event} &
done

## wait for all background processes to finish --> non-ideal as we would rather "stream" jobs launching
wait

## increment nloop counter
((nloop++))

## perform check now to end loop : if current time is greater than projected end time, break.
local current_time=$( date +"%s" )
(( ${current_time} <= ${end_time} ))
do
continue
done
}
export -f MkFitLoop

########################################
## Dump Info about Test into Tmp File ##
########################################

function AppendTmpFile ()
{
local tmp_output_file=${1}
local ncore=${2}
local nproc=${3}
local nloop=${4}

echo "${ncore_label} ${ncore}" >> "${tmp_output_file}"
echo "${nproc_label} ${nproc}" >> "${tmp_output_file}"
echo "${nloop_label} ${nloop}" >> "${tmp_output_file}"
}
export -f AppendTmpFile

####################################
## Dump Tmp Output into Main File ##
####################################

function DumpIntoFile ()
{
local tmp_output_file=${1}
local output_file=${2}

## get wall-clock time, split
read -ra time_arr < <(grep "real" "${tmp_output_file}")
local tmp_time=${time_arr[1]}

local mins=$( echo "${tmp_time}" | cut -d "m" -f 1 )
local secs=$( echo "${tmp_time}" | cut -d "m" -f 2 | cut -d "s" -f 1 )

local total_time=$( bc -l <<< "${mins} * 60 + ${secs}" )

## get physical cores used
local ncore=$( grep "${ncore_label}" "${tmp_output_file}" | cut -d " " -f 2 )

## compute total events processed per core
local nloop=$( grep "${nloop_label}" "${tmp_output_file}" | cut -d " " -f 2 )
local nproc=$( grep "${nproc_label}" "${tmp_output_file}" | cut -d " " -f 2 )

local total_proc=$(( ${nloop} * ${nproc} ))
local total_proc_per_core=$( bc -l <<< "${total_proc} / ${ncore}" )

## divide time by total events processed per core
local norm_time=$( bc -l <<< "${total_time} / ${total_proc_per_core}" )

## dump result into final output file
echo "${test_label} ${norm_time}" >> "${output_file}"
}
export -f DumpIntoFile

0 comments on commit 1da2566

Please sign in to comment.