Skip to content

Commit

Permalink
CcdCallbacks: only call timers when necessary (#3537)
Browse files Browse the repository at this point in the history
Added CcdCondFn to avoid timers in condition-based callbacks and
changed the return type of CcdRaiseCondition to enable only calling
timers when necessary, decreasing the scheduling overhead. Also only
call CcdCallBacks() when there are periodic callbacks registered.

Define a macro for backwards compatibility, i.e. users can check
"#if CCD_COND_FN_EXISTS" in application code.
  • Loading branch information
stwhite91 committed Mar 24, 2022
1 parent 5b5234d commit 245542a
Show file tree
Hide file tree
Showing 45 changed files with 232 additions and 232 deletions.
24 changes: 12 additions & 12 deletions benchmarks/charm++/communication_overhead/overhead_test.C
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ int nCycles = 100; // Number of iterations for each message size

CProxy_TestDriver testDriverProxy;

void idleStartHandler(void *timingGroupObj, double start);
void idleEndHandler(void *timingGroupObj, double cur);
void idleStartHandlerArray(void *timingGroupObj, double start);
void idleEndHandlerArray(void *timingGroupObj, double cur);
void idleStartHandler(void *timingGroupObj);
void idleEndHandler(void *timingGroupObj);
void idleStartHandlerArray(void *timingGroupObj);
void idleEndHandlerArray(void *timingGroupObj);

class SimpleMessage: public CMessage_SimpleMessage {
public:
Expand Down Expand Up @@ -357,28 +357,28 @@ public:

};

void idleStartHandler(void *timingGroupObj, double start) {
void idleStartHandler(void *timingGroupObj) {
CommunicationGroup *localInstance = (CommunicationGroup *) timingGroupObj;
localInstance->startIdleTime = start;
localInstance->startIdleTime = CkWallTimer();
}

void idleEndHandler(void *timingGroupObj, double cur) {
void idleEndHandler(void *timingGroupObj) {
CommunicationGroup *localInstance = (CommunicationGroup *) timingGroupObj;
if(localInstance->startIdleTime > 0) {
localInstance->iterationIdleTime += cur - localInstance->startIdleTime;
localInstance->iterationIdleTime += CkWallTimer() - localInstance->startIdleTime;
localInstance->startIdleTime = -1;
}
}

void idleStartHandlerArray(void *timingGroupObj, double start) {
void idleStartHandlerArray(void *timingGroupObj) {
CommunicationArray *localInstance = (CommunicationArray *) timingGroupObj;
localInstance->startIdleTime = start;
localInstance->startIdleTime = CkWallTimer();
}

void idleEndHandlerArray(void *timingGroupObj, double cur) {
void idleEndHandlerArray(void *timingGroupObj) {
CommunicationArray *localInstance = (CommunicationArray *) timingGroupObj;
if(localInstance->startIdleTime > 0) {
localInstance->iterationIdleTime += cur - localInstance->startIdleTime;
localInstance->iterationIdleTime += CkWallTimer() - localInstance->startIdleTime;
localInstance->startIdleTime = -1;
}
}
Expand Down
8 changes: 4 additions & 4 deletions benchmarks/converse/machinetest/multiping.C
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,18 @@ CpvDeclare(double, IdleStartTime);
CpvDeclare(double, IdleTime);

//Register Idle time handlers
void ApplIdleStart(void *, double start)
void ApplIdleStart(void *)
{
CpvAccess(IdleStartTime)= start; //CmiWallTimer();
CpvAccess(IdleStartTime) = CmiWallTimer();
return;
}

void ApplIdleEnd(void *, double cur)
void ApplIdleEnd(void *)
{
if(CpvAccess(IdleStartTime) < 0)
return;

CpvAccess(IdleTime) += cur /*CmiWallTimer()*/-CpvAccess(IdleStartTime);
CpvAccess(IdleTime) += CmiWallTimer() - CpvAccess(IdleStartTime);
CpvAccess(IdleStartTime)=-1;
return;
}
Expand Down
8 changes: 4 additions & 4 deletions benchmarks/converse/machinetest/pingall.C
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,18 @@ CpvDeclare(double, IdleStartTime);
CpvDeclare(double, IdleTime);

//Registering idle handlers
void ApplIdleStart(void *, double start)
void ApplIdleStart(void *)
{
CpvAccess(IdleStartTime)= start; //CmiWallTimer();
CpvAccess(IdleStartTime) = CmiWallTimer();
return;
}

void ApplIdleEnd(void *, double cur)
void ApplIdleEnd(void *)
{
if(CpvAccess(IdleStartTime) < 0)
return;

CpvAccess(IdleTime) += cur /*CmiWallTimer()*/-CpvAccess(IdleStartTime);
CpvAccess(IdleTime) += CmiWallTimer() - CpvAccess(IdleStartTime);
CpvAccess(IdleStartTime)=-1;
return;
}
Expand Down
3 changes: 1 addition & 2 deletions doc/charm++/manual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4395,8 +4395,7 @@ whenidle
priority or speculative) in the absence of other work. ``whenidle``
entry methods must return a ``bool`` value, indicating whether the
entry method should be called when the processor is idle again, and
accept a ``double`` argument representing the current timestamp. An
example can be found in ``examples/charm++/whenidle``.
take no arguments. An example can be found in ``examples/charm++/whenidle``.

python
entry methods are enabled to be called from python scripts as
Expand Down
26 changes: 11 additions & 15 deletions doc/converse/manual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2002,18 +2002,18 @@ CcdUSERMAX

.. code-block:: c++

int CcdCallOnCondition(int condnum, CcdVoidFn fnp, void* arg)
int CcdCallOnCondition(int condnum, CcdCondFn fnp, void* arg)

This call instructs the system to call the function indicated by the
function pointer ``fnp``, with the specified argument ``arg``, when
the condition indicated by ``condnum`` is raised next. Multiple
functions may be registered for the same condition number.
``CcdVoidFn`` is a function pointer with the signature ``void fnp(void
*userParam, double curWallTime)``
``CcdCondFn`` is a function pointer with the signature ``void fnp(void
*userParam)``

.. code-block:: c++

int CcdCallOnConditionKeep(int condnum, CcdVoidFn fnp, void* arg)
int CcdCallOnConditionKeep(int condnum, CcdCondFn fnp, void* arg)

As above, but the association is permanent- the given function will
be called again whenever this condition is raised.
Expand All @@ -2032,20 +2032,11 @@ callbacks from within ccd callbacks.

.. code-block:: c++

double CcdRaiseCondition(int condNum)

void CcdRaiseCondition(int condNum)

When this function is called, it invokes all the functions whose
pointers were registered for the ``condNum`` via a *prior* call to
``CcdCallOnCondition`` or ``CcdCallOnConditionKeep``. The function
internally calls ``CmiWallTimer`` and returns this value. When using
``CcdRaiseCondition``, the return value can be used to determine the
current walltime avoiding an additional call to ``CmiWallTimer``.
However, it is important to note that the walltime value returned
by ``CcdRaiseCondition`` could be stale by the time it is returned
since registered functions are executed between the timer call and
the return. For this reason, this walltime value returned should be
used in situations where an exact or current timer value is not desired.
``CcdCallOnCondition`` or ``CcdCallOnConditionKeep``.

.. code-block:: c++

Expand All @@ -2056,6 +2047,11 @@ be called at least ``msLater`` milliseconds later. The registered
function ``fnp`` is actually called the first time the scheduler gets
control after ``deltaT`` milliseconds have elapsed. The default
polling resolution for timed callbacks is 5 ms.
``CcdVoidFn`` is a function pointer with the signature ``void fnp(void
*userParam, double currWallTime)``. Note the extra wall-time parameter,
which differs from ``CcdCondFn``, because the runtime system internally
calls a timer in order to invoke periodic callbacks. It passes that
time into the user callback as well to avoid the need for extra timer calls.

.. code-block:: c++

Expand Down
2 changes: 1 addition & 1 deletion examples/charm++/whenidle/idlework.C
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ void Test::registerIdleWork() {
CkCallWhenIdle(CkIndex_Test::idleProgress(0), this);
}

bool Test::idleProgress(double time) {
bool Test::idleProgress() {
static bool calledBefore = false;
CkPrintf("[TEST] Idle Work Called, CalledBefore=%d.\n", (int)calledBefore);
calledBefore = !calledBefore;
Expand Down
2 changes: 1 addition & 1 deletion examples/charm++/whenidle/idlework.ci
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mainmodule idlework {
array [1D] Test {
entry Test();
entry void registerIdleWork();
entry [whenidle] bool idleProgress(double);
entry [whenidle] bool idleProgress();
};
}

2 changes: 1 addition & 1 deletion examples/charm++/whenidle/idlework.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Test : public CBase_Test {
public:
Test(CkMigrateMessage *m) {}
Test();
bool idleProgress(double time);
bool idleProgress();
void registerIdleWork();
};

Expand Down
4 changes: 2 additions & 2 deletions src/arch/cuda/hybridAPI/hapi_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ void hapiInit(char** argv) {

#ifndef HAPI_CUDA_CALLBACK
// Register polling function to be invoked at every scheduler loop
CcdCallOnConditionKeep(CcdSCHEDLOOP, hapiPollEvents, NULL);
CcdCallOnConditionKeep(CcdSCHEDLOOP, (CcdCondFn)hapiPollEvents, NULL);
#endif
}

Expand Down Expand Up @@ -1381,7 +1381,7 @@ void hapiClearInstrument() {
// all successive completed events in the queue starting from the front.
// TODO Maybe we should make one pass of all events in the queue instead,
// since there might be completed events later in the queue.
void hapiPollEvents(void* param, double cur_time) {
void hapiPollEvents(void* param) {
#ifndef HAPI_CUDA_CALLBACK
if (CpvAccess(n_hapi_events) <= 0) return;

Expand Down
2 changes: 1 addition & 1 deletion src/arch/cuda/hybridAPI/hapi_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ void hapiInit(char** argv);
void hapiExit();

// Polls for GPU work completion. Does not do anything if HAPI_CUDA_CALLBACK is defined.
void hapiPollEvents(void* param, double cur_time);
void hapiPollEvents(void* param);

// BufferPool constructs for mempool implementation.
// Data and metadata reside in same chunk of memory.
Expand Down
6 changes: 3 additions & 3 deletions src/arch/gni/machine.C
Original file line number Diff line number Diff line change
Expand Up @@ -1900,19 +1900,19 @@ void LrtsPostCommonInit(int everReturn)

#if !CMK_SMP
if (useDynamicSMSG)
CcdCallOnConditionKeep(CcdPERIODIC_10ms, (CcdVoidFn) PumpDatagramConnection, NULL);
CcdCallOnConditionKeep(CcdPERIODIC_10ms, (CcdCondFn) PumpDatagramConnection, NULL);
#endif

#if ! LARGEPAGE
if (_checkProgress)
#if CMK_SMP
if (CmiMyRank() == 0)
#endif
CcdCallOnConditionKeep(CcdPERIODIC_2minute, (CcdVoidFn) CheckProgress, NULL);
CcdCallOnConditionKeep(CcdPERIODIC_2minute, (CcdCondFn) CheckProgress, NULL);
#endif

#if !LARGEPAGE
CcdCallOnCondition(CcdTOPOLOGY_AVAIL, (CcdVoidFn)set_limit, NULL);
CcdCallOnCondition(CcdTOPOLOGY_AVAIL, (CcdCondFn)set_limit, NULL);
#endif
}

Expand Down
8 changes: 4 additions & 4 deletions src/arch/netlrts/machine.C
Original file line number Diff line number Diff line change
Expand Up @@ -1863,14 +1863,14 @@ void LrtsPostCommonInit(int everReturn)
#if CMK_SHARED_VARS_UNAVAILABLE
if (Cmi_netpoll) /*Repeatedly call CommServer*/
CcdCallOnConditionKeep(CcdPERIODIC,
(CcdVoidFn) CommunicationPeriodic, NULL);
(CcdCondFn) CommunicationPeriodic, NULL);
else /*Only need this for retransmits*/
CcdCallOnConditionKeep(CcdPERIODIC_10ms,
(CcdVoidFn) CommunicationPeriodic, NULL);
(CcdCondFn) CommunicationPeriodic, NULL);
#endif

if (CmiMyRank()==0 && Cmi_charmrun_fd!=-1) {
CcdCallOnConditionKeep(CcdPERIODIC_10ms, (CcdVoidFn) CmiStdoutFlush, NULL);
CcdCallOnConditionKeep(CcdPERIODIC_10ms, (CcdCondFn) CmiStdoutFlush, NULL);
#if CMK_SHARED_VARS_UNAVAILABLE && !CMK_TIMER_USE_WIN32API
if (!Cmi_asyncio) {
CcdCallFnAfter((CcdVoidFn)pingCharmrunPeriodic,NULL,1000);
Expand Down Expand Up @@ -1909,7 +1909,7 @@ void LrtsPostCommonInit(int everReturn)
/* Call the function to periodically call the token adapt function */
CcdCallFnAfter((CcdVoidFn)TokenUpdatePeriodic, NULL, 2000); // magic number of 2000ms
CcdCallOnConditionKeep(CcdPERIODIC_10s, // magic number of PERIOD 10s
(CcdVoidFn) TokenUpdatePeriodic, NULL);
(CcdCondFn) TokenUpdatePeriodic, NULL);
#endif

#ifdef CMK_RANDOMLY_CORRUPT_MESSAGES
Expand Down
2 changes: 1 addition & 1 deletion src/arch/pami/machine.C
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,7 @@ void PerrorExit (const char *err) {
exit (-1);
}

static void CmiNotifyIdleCcd(void *ignored1, double ignored2)
static void CmiNotifyIdleCcd(void *ignored)
{
CmiNotifyIdle();
}
Expand Down
8 changes: 4 additions & 4 deletions src/arch/util/machine-common-core.C
Original file line number Diff line number Diff line change
Expand Up @@ -1580,12 +1580,12 @@ static void ConverseRunPE(int everReturn) {
#if CMK_SMP
{
CmiIdleState *sidle=CmiNotifyGetState();
CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)CmiNotifyBeginIdle,(void *)sidle);
CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyStillIdle,(void *)sidle);
CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdCondFn)CmiNotifyBeginIdle,(void *)sidle);
CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdCondFn)CmiNotifyStillIdle,(void *)sidle);
}
#else
CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)CmiNotifyBeginIdle, NULL);
CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyStillIdle, NULL);
CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdCondFn)CmiNotifyBeginIdle, NULL);
CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdCondFn)CmiNotifyStillIdle, NULL);
#endif


Expand Down
8 changes: 4 additions & 4 deletions src/arch/verbs/machine.C
Original file line number Diff line number Diff line change
Expand Up @@ -1860,14 +1860,14 @@ void LrtsPostCommonInit(int everReturn)
#if CMK_SHARED_VARS_UNAVAILABLE
if (Cmi_netpoll) /*Repeatedly call CommServer*/
CcdCallOnConditionKeep(CcdPERIODIC,
(CcdVoidFn) CommunicationPeriodic, NULL);
(CcdCondFn) CommunicationPeriodic, NULL);
else /*Only need this for retransmits*/
CcdCallOnConditionKeep(CcdPERIODIC_10ms,
(CcdVoidFn) CommunicationPeriodic, NULL);
(CcdCondFn) CommunicationPeriodic, NULL);
#endif

if (CmiMyRank()==0 && Cmi_charmrun_fd!=-1) {
CcdCallOnConditionKeep(CcdPERIODIC_10ms, (CcdVoidFn) CmiStdoutFlush, NULL);
CcdCallOnConditionKeep(CcdPERIODIC_10ms, (CcdCondFn) CmiStdoutFlush, NULL);
#if CMK_SHARED_VARS_UNAVAILABLE
if (!Cmi_asyncio) {
/* gm cannot live with setitimer */
Expand Down Expand Up @@ -1908,7 +1908,7 @@ void LrtsPostCommonInit(int everReturn)
/* Call the function to periodically call the token adapt function */
CcdCallFnAfter((CcdVoidFn)TokenUpdatePeriodic, NULL, 2000); // magic number of 2000ms
CcdCallOnConditionKeep(CcdPERIODIC_10s, // magic number of PERIOD 10s
(CcdVoidFn) TokenUpdatePeriodic, NULL);
(CcdCondFn) TokenUpdatePeriodic, NULL);
#endif

#ifdef CMK_RANDOMLY_CORRUPT_MESSAGES
Expand Down
14 changes: 7 additions & 7 deletions src/ck-core/ck.C
Original file line number Diff line number Diff line change
Expand Up @@ -2771,8 +2771,8 @@ private:
}
};

void CkMessageReplayQuiescence(void *rep, double time);
void CkMessageDetailReplayDone(void *rep, double time);
void CkMessageReplayQuiescence(void *rep);
void CkMessageDetailReplayDone(void *rep);

class CkMessageReplay : public CkMessageWatcher {
int counter;
Expand Down Expand Up @@ -2899,7 +2899,7 @@ public:
getNext();
REPLAYDEBUG("Constructing ckMessageReplay: "<< nextPE <<" "<< nextSize <<" "<<nextEvent);
#if CMI_QD
if (CkMyPe()==0) CmiStartQD(CkMessageReplayQuiescence, this);
if (CkMyPe()==0) CmiStartQD((CcdCondFn)CkMessageReplayQuiescence, this);
#endif
}
~CkMessageReplay() {fclose(f);}
Expand Down Expand Up @@ -2998,7 +2998,7 @@ public:

CsdEnqueue(getNext());

CcdCallOnCondition(CcdPROCESSOR_STILL_IDLE, (CcdVoidFn)CkMessageDetailReplayDone, (void*)this);
CcdCallOnCondition(CcdPROCESSOR_STILL_IDLE, (CcdCondFn)CkMessageDetailReplayDone, (void*)this);
}
virtual bool process(envelope **env,CkCoreState *ck) {
void *msg = getNext();
Expand All @@ -3007,13 +3007,13 @@ public:
}
};

void CkMessageReplayQuiescence(void *rep, double time) {
void CkMessageReplayQuiescence(void *rep) {
CkPrintf("[%d] Quiescence detected\n",CkMyPe());
CkMessageReplay *replay = (CkMessageReplay*)rep;
//CmiStartQD(CkMessageReplayQuiescence, replay);
//CmiStartQD((CcdCondFn)CkMessageReplayQuiescence, replay);
}

void CkMessageDetailReplayDone(void *rep, double time) {
void CkMessageDetailReplayDone(void *rep) {
CkMessageDetailReplay *replay = (CkMessageDetailReplay *)rep;
CkPrintf("[%d] Detailed replay finished after %f seconds. Exiting.\n",CkMyPe(),CkWallTimer()-replay->starttime);
ConverseExit();
Expand Down
4 changes: 2 additions & 2 deletions src/ck-core/ckarray.C
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ inline void CkArray::springCleaning(void)
setupSpringCleaning();
}

void CkArray::staticSpringCleaning(void* forArray, double curWallTime)
void CkArray::staticSpringCleaning(void* forArray)
{
((CkArray*)forArray)->springCleaning();
}
Expand All @@ -539,7 +539,7 @@ void CkArray::setupSpringCleaning()
// set up broadcast cleaner
if (!stableLocations)
springCleaningCcd =
CcdCallOnCondition(CcdPERIODIC_1minute, staticSpringCleaning, (void*)this);
CcdCallOnCondition(CcdPERIODIC_1minute, (CcdCondFn)CkArray::staticSpringCleaning, (void*)this);
}

/********************* Little CkArray Utilities ******************/
Expand Down
2 changes: 1 addition & 1 deletion src/ck-core/ckarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,7 @@ class CkArray : public CkReductionMgr

// Spring cleaning
void springCleaning(void);
static void staticSpringCleaning(void* forWhom, double curWallTime);
static void staticSpringCleaning(void* forWhom);
void setupSpringCleaning();
int springCleaningCcd;

Expand Down

0 comments on commit 245542a

Please sign in to comment.