Docker-in-Docker (DinD) capabilities of public runners deactivated. More info

Commit 7029fa22 authored by dino's avatar dino
Browse files

Add counters of elapsed time and CPU time for all actors

git-svn-id: svn://gal-serv.lnl.infn.it/agata/trunk/narval_emulator@1313 170316e4-aea8-4b27-aad4-0380ec0519c9
parent 8b354159
......@@ -75,6 +75,18 @@ void ChainOfActors::Run()
int ping = 0; // input
int pong = 1; // output
#if 1
#define TIMEIT0() \
double wT0 = get_wall_time();\
double cT0 = get_cpu_time();
#define TIMEIT1() \
ptrActor->wTotTime += get_wall_time() - wT0;\
ptrActor->cTotTime += get_cpu_time() - cT0;
#else
#define TIMEIT0()
#define TIMEIT1()
#endif
bool hasError = false;
for(indActor = 0 ; indActor < numActors; indActor++) {
ptrActor = &theActors[indActor];
......@@ -82,8 +94,10 @@ void ChainOfActors::Run()
if(ptrActor->libType == PRODUCER) {
void *bufinp = NULL; // no input buffer for producers
void *bufout = (void *)ioBuffers[pong]; // output buffer is always [pong]
TIMEIT0()
static_cast<NarvalProducer *>(ptrActor->nrvPointer)->process_block(
bufout, ptrActor->sizeOut, &used_of_output_buffer, &error_code); // producers use ptrActor->sizeOut
TIMEIT1()
if(error_code)
hasEnded = true;
if(used_of_output_buffer == 0) {
......@@ -97,12 +111,14 @@ void ChainOfActors::Run()
else if(ptrActor->libType == BUILDER) {
void *bufinp = NULL; // builders are producers ==> no input buffer
void *bufout = (void *)ioBuffers[pong]; // output buffer is always [pong]
TIMEIT0()
#ifdef EVB_INHERITS_FROM_NARVAL_PRODUCER
static_cast<NarvalProducer *>(ptrActor->nrvPointer)->process_block(
#else
ptrActor->evbPointer->process_block(
#endif
bufout, ptrActor->sizeOut, &used_of_output_buffer, &error_code); // builders use ptrActor->sizeOut
TIMEIT1()
if(error_code)
hasEnded = true;
if(used_of_output_buffer == 0) {
......@@ -118,9 +134,11 @@ void ChainOfActors::Run()
CheckBufferSize(pong, OBG*size_of_input_buffer); // worst case is AncillaryFilterVME which needs ~2.85
void *bufinp = (void *)ioBuffers[ping]; // input buffer is always [ping]
void *bufout = (void *)ioBuffers[pong]; // input buffer is always [pong]
TIMEIT0()
static_cast<NarvalFilter *>(ptrActor->nrvPointer)->process_block(
bufinp, size_of_input_buffer,
bufout, ioBufflen[pong], &used_of_output_buffer, &error_code);
TIMEIT1()
dispatchFlag = (used_of_output_buffer > 0);
if(error_code) {
hasError = true;
......@@ -129,7 +147,7 @@ void ChainOfActors::Run()
if(used_of_output_buffer == 0)
break;
swap(ping, pong); // swap buffers for the next actor
size_of_input_buffer = used_of_output_buffer; // and remembber the actual size
size_of_input_buffer = used_of_output_buffer; // and remember the actual size
}
// CONSUMERS
else if(ptrActor->libType == CONSUMER) {
......@@ -137,8 +155,10 @@ void ChainOfActors::Run()
continue; // is a "none" fake consumer
void *bufinp = (void *)ioBuffers[ping]; // input buffer is always [ping]
void *bufout = NULL; // no output buffer for consumers
TIMEIT0()
static_cast<NarvalConsumer *>(ptrActor->nrvPointer)->process_block(
bufinp, size_of_input_buffer, &error_code);
TIMEIT1()
if(error_code) {
hasError = true;
break;
......@@ -151,7 +171,9 @@ void ChainOfActors::Run()
dispatchBuff = (void *)ioBuffers[ping];
dispatchSize = size_of_input_buffer;
dispatchFlag = true;
TIMEIT0()
Dispatch();
TIMEIT1()
}
// DISPATCHERS don't swap the buffers, as they are the last in the execution chain.
// Notice that the ping/pong mechanism cannot be restarted until Dispatch has succeeded
......@@ -277,4 +299,32 @@ bool ChainOfActors::ResizeBuffer(int nn, int size)
return true;
}
double ChainOfActors::TotalWTime()
{
double total = 0;
for (indActor = 0; indActor < numActors; indActor++) {
total += theActors[indActor].wTotTime;
}
return total;
}
double ChainOfActors::TotalCTime()
{
double total = 0;
for (indActor = 0; indActor < numActors; indActor++) {
total += theActors[indActor].cTotTime;
}
return total;
}
std::string actor::Who()
{
string who = libConf;
stringTrim(who);
if (who.back() == '/')
who.pop_back();
if (who.find("/")) {
size_t ll = (int)who.find_last_of('/');
who = who.substr(ll+1);
}
return who;
}
......@@ -2,6 +2,7 @@
#define CHAINOFACTORS_H_INCLUDED
#include "NarvalInterface.h"
#include <ctime>
enum EActor { NONE, BUILDER, PRODUCER, FILTER, CONSUMER, DISPATCHER };
......@@ -19,9 +20,13 @@ struct actor {
ADF::NarvalInterface *nrvPointer; // pointer to the actor if Narval-inherited
EventBuilder *evbPointer; // pointer to the actor if EventBuilder
UInt_t sizeOut; // size of output buffer for PRODUCERs and BUILDERs (FILTERs get WCT_BUFSIZE)
double wTotTime; // total wall time (seconds) spent in this actor
double cTotTime; // total cpu time (seconds) spent in this actor
actor(Int_t id = -1) : myIndex(id), libType((EActor)NONE), libItem(-1),
nrvPointer(NULL), evbPointer(NULL), sizeOut(0) {}
nrvPointer(NULL), evbPointer(NULL), sizeOut(0),
wTotTime(0), cTotTime(0) {}
std::string Who();
};
class ChainOfActors {
......@@ -85,7 +90,8 @@ public:
bool ResizeBuffers(int size = 0) {
return ResizeBuffer(0, size) && ResizeBuffer(1, size);
}
double TotalWTime();
double TotalCTime();
};
#endif // CHAINOFACTORS_H_INCLUDED
......@@ -2,10 +2,10 @@
// This is femul (previously named WinCtest), a Narval emulator written as a standalone program
// to help developing and debugging the AGATA data acquisition and analysis (replay) software.
//
// The development started in ~2008, inspired by Joa's C_Test.c (which uses the .so libraries via dlopen, dlsym,...)
// and has evolved towards an almost complete emulation of the Narval environment.
// The main difference/limitation with the Narval implementation is the use of a single process on a single computer.
// To speed-up execution in multi-core computers it is possible to run parallel threads
// The development started in ~2008, inspired by Joa's C_Test.c (which used the .so libraries via dlopen, dlsym,...)
// and has evolved towards a rather complete emulation of the Narval environment.
// The main difference/limitation with respect to Narval is the use of a single process on a single computer.
// However, to achieve execution speed it is possible to run parallel threads :
// - in the PSAFilter library using boost:thread or std::future if the compiler upports the c++11 standard
// - in the driver program (using boost::thread or std::thread) (if #define WCT_THREADED in ChainLocker.h).
//
......@@ -14,9 +14,9 @@
//
// A C++ implementation of the EventBuilder replaces that of Narval (which is written in Ada).
//
// The program is supposed to be multi-platform and has been tested in Windows, [Cygwin??] and GNU/Linux.
// The program is supposed to be multi-platform and has been tested in Windows, GNU/Linux and MacOS.
//
// Dino Bazzacco 2008-2014
// Dino Bazzacco 2008-2018
//
#include <cstdlib>
......@@ -102,6 +102,7 @@ DISPATCHER BuilderName pseudo actor to connect the output of a chain to an i
#endif
#include "AGAPRO_BasicATSB.h" // 36 360
// 4 CONSUMER
// None // 40 400 fake, used as last of a chain
#include "BasicAFC.h" // 41 410 no mother-daughter model
......@@ -168,7 +169,7 @@ struct builder_t {
};
vector<builder_t *> theBuilders;
void showWhat();
void showWhat(); // info on running environment
void getparams(int, char **);
void numparams(char *, int);
void listKeysAndExit(); // call GetParameters(doList=true) and exit
......@@ -291,12 +292,15 @@ AGAIN_LOOP:
// Statistics of chains
cout << endl;
cout << "chain" << setw(12) << "Started" << setw(12) << "Counted" << setw(12) << "DoSleep" << endl;
cout << "chain" << setw(12) << "Started" << setw(12) << "Counted" << setw(12) << "DoSleep"
<< setw(15) << "wall time (s)" << setw(15) << " cpu time (s)" << endl;
for( size_t ich = 0; ich < theChains.size(); ich++) {
cout << setw( 5) << theChains[ich]->myIndex;
cout << setw(12) << theChains[ich]->statStarted;
cout << setw(12) << theChains[ich]->statCounted;
cout << setw(12) << theChains[ich]->statDoSleep;
cout << setw(15) << theChains[ich]->TotalWTime();
cout << setw(15) << theChains[ich]->TotalCTime();
cout << endl;
}
......@@ -1644,8 +1648,12 @@ bool topologyStop()
return false;
}
else {
if(printmsg)
if (printmsg) {
cout << setw(32) << left << " "+pActor->Who()+"-"+ pActor->libName << right
<< " elapsed time = " << setw(8) << setprecision(1) << fixed << pActor->wTotTime << " s "
<< " cpu time = " << setw(8) << setprecision(1) << fixed << pActor->cTotTime << " s" << endl;
cout << pActor->libName << "->process_stop ... done." << endl;
}
}
}
......
......@@ -298,7 +298,7 @@ void EventBuilder::Process(void *obuffer, unsigned int osize, unsigned int *used
// Check if the mandatory keys are present
if (evValid && uMandatoryKeyIn.size()) { // && fActualClass == "EventMerger" moved to InitKeys
UInt_t size = uMandatoryKeyIn.size();
UInt_t size = (UInt_t)uMandatoryKeyIn.size();
for (UInt_t ikey = 0; ikey < size; ikey++)
bMandatoryKeyIn[ikey] = false;
for (UInt_t nn = 0; nn < nQueues; nn++) {
......
......@@ -6,6 +6,8 @@
#include <cmath>
#include <cstring>
#include <chrono>
#include <random>
#include <climits>
using namespace std;
......@@ -166,13 +168,19 @@ void CycleServer::Exec(uint64_t tstNew, int nevts) {
SetTstStep(tst1second*secMinStep);
tstWrite = tstThis + tstStep;
// to avoid clogging the machine with all actors writing the spectra at the same time,
// add a random delay (obtained from the time registers) of up to secMinStep to the various actors
// add a (truly) random delay of up to secMinStep to the various actors
#if 1
std::random_device rdv;
auto irn = rdv();
double rrrr = double(rdv()) / double(UINT_MAX); // use the second value of rdv
#else
double rrrr = get_wall_time();
rrrr += get_cpu_time() * 12345.; // increase randomness ??
rrrr -= floor(rrrr); // keep fractional part
rrrr *= secMinStep; // scale to secMinStep
#endif
tstWrite += uint64_t(tst1second*rrrr);
lastWrite = get_wall_time();
auto now = std::chrono::system_clock::now();
}
if(tstThis >= tstWrite) { // time to write
......
......@@ -744,16 +744,16 @@ bool InvertMatrix4(const double m[16], double invOut[16])
#ifdef _WIN32
// Windows
#include <Windows.h>
double get_wall_time(){
LARGE_INTEGER time,freq;
if (!QueryPerformanceFrequency(&freq)){
return 0; // Handle error
}
if (!QueryPerformanceCounter(&time)){
return 0; // Handle error
}
return (double)time.QuadPart / freq.QuadPart;
}
//double get_wall_time(){
// LARGE_INTEGER time,freq;
// if (!QueryPerformanceFrequency(&freq)){
// return 0; // Handle error
// }
// if (!QueryPerformanceCounter(&time)){
// return 0; // Handle error
// }
// return (double)time.QuadPart / freq.QuadPart;
//}
double get_cpu_time(){
FILETIME a,b,c,d;
if (GetProcessTimes(GetCurrentProcess(), &a, &b, &c, &d) != 0) {
......@@ -768,17 +768,17 @@ double get_cpu_time(){
}
#else
// Posix/Linux
// Posix/Linux (innline functions in Misc.h)
#include <sys/time.h>
double get_wall_time(){
struct timeval time;
if (gettimeofday(&time,NULL)){
return 0; // Handle error
}
return (double)time.tv_sec + (double)time.tv_usec * .000001;
}
double get_cpu_time(){
return (double)clock() / CLOCKS_PER_SEC;
}
//double get_wall_time(){
// struct timeval time;
// if (gettimeofday(&time,NULL)){
// return 0; // Handle error
// }
// return (double)time.tv_sec + (double)time.tv_usec * .000001;
//}
//double get_cpu_time(){
// return (double)clock() / CLOCKS_PER_SEC;
//}
#endif
......@@ -4,8 +4,20 @@
#include <string>
#include <vector>
double get_wall_time();
double get_cpu_time();
#include <chrono>
inline double get_wall_time() {
std::chrono::duration<double> td = std::chrono::system_clock::now().time_since_epoch();
return td.count();
}
#ifdef _WIN32
double get_cpu_time();
#else
#include <ctime>
inline double get_cpu_time() {
return (double)std::clock() / CLOCKS_PER_SEC;
}
#endif
void stringTrim(std::string &str);
bool stringTrim(std::string &str, const std::string& cmt);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment