5 research outputs found

    The Backstroke framework for source level reverse computation applied to parallel discrete event simulation

    Full text link
    This report introduces Backstroke, a new open source framework for the automatic generation of reverse code for functions written in C++. Backstroke enables reverse computation for optimistic parallel discrete event simulations. It is built over the ROSE open- source compiler infrastructure, and handles complex C++ features including pointers and pointer types, arrays, function and method calls, class types. inheritance, polymorphism, virtual functions, abstract classes, templated classes and containers. Backstroke also introduces new program inversion techniques based on advanced compiler analysis tools built into ROSE. We explore and illustrate some of the complex language and semantic issues that arise in generating correct reverse code for C++ functions

    The Backstroke Framework for Source Level Reverse Computation Applied to Parallel Discrete Event Simulation THE BACKSTROKE FRAMEWORK FOR SOURCE LEVEL REVERSE COMPUTATION APPLIED TO PARALLEL DISCRETE EVENT SIMULATION

    No full text
    ABSTRACT We introduce Backstroke, a new open source framework for the automatic generation of reverse code for functions written in C++. Backstroke enables reverse computation for optimistic parallel discrete event simulations. It is built over the ROSE open-source compiler infrastructure, and handles complex C++ features including pointers and pointer types, arrays, function and method calls, class types, inheritance, polymorphism, virtual functions, abstract classes, templated classes and containers. Backstroke also introduces new program inversion techniques based on advanced compiler analysis tools built into ROSE. We explore and illustrate some of the complex language and semantic issues that arise in generating correct reverse code for C++ functions. INTRODUCTION Backstroke is a new open source framework for the automatic generation of reverse code for functions written in C++. It is built on ROSE, a widely used source-to-source compiler infrastructure that has been under development at Lawrence Livermore National Laboratory for a decade (Quinlan 2011). The primary purpose of Backstroke is to enable reverse computation for fast, efficient rollback in optimistic parallel discrete event simulations. Reverse computation is a well established technique now, but major practical barriers still prevent its widespread adoption. It is difficult to create correct and efficient reverse methods by hand, and unrealistic to require programmers to do so. Further, since the number of times an event is rolled back is unpredictable, simple bugs in reverse code frequently act as nondeterministic "Heisenbugs", making debugging very difficult. These considerations suggest automatic generation of reverse code CONTEXT AND RELATED WORK A parallel discrete event simulation (PDES) program consists of logical processes (LPs) that execute concurrently and exchange timestamped event messages. A synchronization algorithm is required to ensure each LP processes events in non-decreasing timestamp order. Optimistic synchronization uses rollback to undo the computation of events that are performed out of timestamp order Backstroke is not a single method or algorithm, but rather a framework designed to accommodate a collection of reverse computation or program inversion methods. Different inversion techniques can be used in different regions of the simulation code as appropriate, or can be applied for different variables of the simulation state depending on their types and usage. Over time Backstroke will evolve by accumulating an ever larger, more sophisticated library of inversion techniques along with more precise criteria for deciding when to use each one. Backstroke's reverse computation capability can be used in a number of ways to automate the creation of optimistic parallel discrete event simulations. It can be used for simulations developed de novo, but it can also help create an optimistic simulation by federating two or more sequential models Even for code in the C-like subset of C++, Backstroke introduces new program inversion techniques that go well beyond those described in previous studies. Path-oriented inversion methods make use of sophisticated program analysis tools, e.g. SSA (static single assignment) value-graph analysis of the flow of data in a function, and interprocedural analysis. Such methods also can handle inversion of escape constructs such as return, break, continue, and throw that cannot be handled in full generality by previous techniques. WHAT BACKSTROKE DOES Backstroke takes all the source code files for a simulation written in C++ and outputs modified source code in which all event methods in the simulation have three new associated methods that are declared and defined in the same scope as the original method. For each event method E() declared as void E(args) the Backstroke system generates three related methods, E_forward(args), E_reverse(args), and E_commit(). Roughly speaking these new methods do the following: Vulov, Hou, Vuduc, Quinlan, Fujimoto, Jefferson void E_forward(args) has essentially the same effect on the simulation state as E(args), but in addition it saves data on a rollback stack (implemented as a double-ended queue) that may be needed in case of rollback to reconstruct the original state before E(args) was called. void E_reverse(args) exactly rolls back the side effects done by E_forward(args), thereby restoring the LP to the state it was in before E_forward(args)was executed. In so doing it consumes the data saved on the rollback stack during the execution of E_forward(args). void E_commit() performs actions that are either irreversible or are unsafe to reverse if executed speculatively in E_forward(args). They thus must be executed later at commit time, when it is certain that the event will not be rolled back. These actions include writing to output streams and deallocating dynamically allocated variables, but some other actions may need to be treated this way as well. E_commit()executes at an unspecified time after E_forward() and is constrained to have no access to the simulation state, so that it neither reads nor modifies it. More formally, for a void event method E(args) the derived methods are required to satisfy the following semantic equations: Equation (a) says roughly that any event method E(args) is equivalent, in the sense of having indistinguishable side effects on simulation state and identical simulation output, to executing E_forward(args) followed by E_commit(args). Thus, whenever in an optimistic simulation an event E is executed for the last time, so that only E_forward(args) and later E_commit() are executed, the behavior is the same as if the original event method E(args) was executed. Equation (b) says that E_forward(args) followed by E_reverse(args) is equivalent to a no-op, i.e. that E_reverse exactly undoes all of the side-effects of E_forward (and does nothing else), leaving the computation in a state equivalent to having done nothing at all, so that E_reverse correctly accomplishes a rollback. These equations are not sufficient to perfectly define the required behavior of the three derived methods. They do not, for example, capture the fact that E_commit() cannot access the LP state variables. Furthermore, method E_forward() followed by E_commit() is not required to leave the computation in exactly the same binary state, bit for bit, as executing E(), and E_forward() followed by E_reverse() also does not have to leave the computation perfectly unchanged in a binary sense. And we do require that E_forward() followed by E_reverse()produces no memory leaks. In both cases, however, the before-and after-LP states must be equivalent in a sense to be made more precise in Section 6.5. Despite these limitations these two equations are very useful in clarifying the requirements for reverse computation. BACKSTROKE AS A ROSE APPLICATION Backstroke is based on the ROSE source-to-source code compiler infrastructure (Quinlan 2011). ROSE is a compiler in that it inputs a source program and outputs an executable binary, but it also allows arbitrary code transformations within the front end. A single execution of ROSE involves the following steps, as illustrated in • The AST is then modified or transformed according to the logic of the particular ROSE application. In the case of Backstroke this transformation is the generation of forward, reverse, and commit methods for every event method. Vulov, Hou, Vuduc, Quinlan, Fujimoto, Jefferson • After the transformation of the AST, ROSE then unparses it to produce C++ source code again. • Finally, the modified code goes through a normal compile-and-build process to produce an executable binary. The second step is the key part of the process that distinguishes one ROSE application from another

    An Agent-Based Simulation API for Speculative PDES Runtime Environments

    Get PDF
    Agent-Based Modeling and Simulation (ABMS) is an effective paradigm to model systems exhibiting complex interactions, also with the goal of studying the emergent behavior of these systems. While ABMS has been effectively used in many disciplines, many successful models are still run only sequentially. Relying on simple and easy-to-use languages such as NetLogo limits the possibility to benefit from more effective runtime paradigms, such as speculative Parallel Discrete Event Simulation (PDES). In this paper, we discuss a semantically-rich API allowing to implement Agent-Based Models in a simple and effective way. We also describe the critical points which should be taken into account to implement this API in a speculative PDES environment, to scale up simulations on distributed massively-parallel clusters. We present an experimental assessment showing how our proposal allows to implement complicated interactions with a reduced complexity, while delivering a non-negligible performance increase

    A Case Study for Reversible Computing: Reversible Debugging of Concurrent Programs

    Get PDF
    International audienceReversible computing allows one to run programs not only in the usual forward direction, but also backward. A main application area for reversible computing is debugging, where one can use reversibility to go backward from a visible misbehaviour towards the bug causing it. While reversible debugging of sequential systems is well understood, reversible debugging of concurrent and distributed systems is less settled. We present here two approaches for debugging concurrent programs, one based on backtracking, which undoes actions in reverse order of execution, and one based on causal consistency, which allows one to undo any action provided that its consequences, if any, are undone beforehand. The first approach tackles an imperative language with shared memory, while the second one considers a core of the functional message-passing language Erlang. Both the approaches are based on solid formal foundations
    corecore