forked from cms-sw/cmssw
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request cms-sw#200 from kmcdermo/stress-test
Stress test scripts
- Loading branch information
Showing
4 changed files
with
555 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.