Download Delayed Side-Effects Ease Multi-Core Programming | CISC 879 and more Papers Computer Science in PDF only on Docsity!
Anil Nair
Dept of Computer & Information Sciences University of Delaware Delayed Side-Effects Ease Multi-core Programming
Paper by : Anton Lokhmotov, Alan Mycroft, and Andrew Richards
Overview
- Introduction.
- Sieve Concept
- Importance of Sieve Construct
- Experimental Evaluation
- Conclusion
Introduction : The Sieve Concept It is an approach to automatic parallelization employed in Codeplay’s Sieve C++ System low level Parallel Programming.
- Guarantees made by the Sieve code:
- Part of the code is enclosed in a special block
- No memory location defined outside of the block is written to and then read from within the block. Ie Block generates no true dependences.
- How it helps?
- Makes code more amenable to auto-parallelization.
- Block-based structure maps well to a natural programming style for emerging heterogeneous hierarchical systems.
Introduction : The Sieve Concept
- How it helps?
- Makes code more amenable to auto-parallelization.
- Block-based structure maps well to a natural programming style for emerging heterogeneous hierarchical systems.
Sieve Concept
- Syntactic extension :
- Part of the code is enclosed in a special block called the SIEVE BLOCK prefixed with the sieve keyword.
- No Memory location defined outside of the block is written to and then read from within the block. Bounded Variable : Variable defined within the lexical scope. Free Variable : Variable defined outside of the lexical scope.
Sieve Concept
- Syntax Programmer opens a new lexical scope (Sieve block) and prefixes it with the sieve keyword. Eg : sieve { int b; ….} //sieve block.
Sieve Concept : Semantics Equivalent to : void f (int *ap) { const int ar = *ap; int aw = *ap; { //Sieve block entry int b ; ….. = ar; aw = ………..; b = ar; } //Sieve block exit *ap = aw; } int main(){ int a; …. f(&a); }
Sieve Concept : Semantics
Understanding change in Semantics :
- Sieve block semantics departs from that of a standard lexical scope.
- Theory of data dependence helps in understanding how.
Data Dependencies :
- True dependency
- Anti dependency
- Output dependency
Anti-dependence If a read of a free variable is followed by a write to it ( anti-dependence ), delaying the write preserves the dependence.
- Anti-dependences present no problem. Eg : int main () int a; sieve { //Sieve block begins ……= a; a = …… }//End of Sieve Block ……}
Output-dependence If a write to a free variable is followed by another write to it ( output dependence ), delaying the writes preserves the dependence if the order of writes is preserved.
- Output dependences can be achieved by replacing every write to a delayed variable with a push of address-value pair onto a FIFO queue.
- Apply all queue writes in order on exit from the sieve block.
- Such a queue is referred to as a side-effect queue.
Example Consider the example : int main() { int a = 0; sieve { int b = 0; a = a + 1; b = b + 1; print(a, b); // prints 0, a = a + 1; b = b + 1; print(a, b); // prints 0, } print(a); // prints 1 }
- The first two print statements behave as expected as writes to the free variable a are delayed until the end of the sieve block,
- Third print statement prints an undesirable answer.
- This result, however, is easy to explain using the CBVDR (call by value delay result) analogy.
Example Continued
- Sieve Block is equivalent to : void f( int *ap) { const int ar = *ap; int aw = *ap; { int b = 0; aw = ar + 1; b = b + 1; print(ar, b); // prints 0, aw = ar + 1; b = b + 1; print(ar, b); // prints 0, } *ap = aw; // *ap = 1, since aw == 1 } int main() { int a = 0; f(&a); // passing ap, where *ap == 0 print(a); // prints 1 }
Function Call
- A common imperative programming style is to use functions for their side-effects.
- For function calls inside a Sieve block, programmer can specify one of the following - Call the function immediately and have its side-effects delayed. - Delay the call itself until end of the block. (Can be useful for I/O.)
Importance of the Sieve Construct
- Delayed Side-effects Facilitate Dependence Analysis
- For effectively exploiting parallel hardware, compiler often requires to re-order computation from the order specified by the programmer.
- Indirect read/write are difficult to reorder. (endemic in C/C++)
- With Sieve Code, compiler assumes that dependencies can only be generated on immediate data.
- This reduces complexity of dependence analysis.
- Makes code fragment more amenable to Parallelization.