celling shim compiling deterministic concurrency to a
play

Celling SHIM: Compiling Deterministic Concurrency to a Heterogeneous - PowerPoint PPT Presentation

Celling SHIM: Compiling Deterministic Concurrency to a Heterogeneous Multicore Nalini Vasudevan and Stephen A. Edwards Columbia University in the City of New York, USA March 2009 Main Points Scheduling-independent message passing works for


  1. Celling SHIM: Compiling Deterministic Concurrency to a Heterogeneous Multicore Nalini Vasudevan and Stephen A. Edwards Columbia University in the City of New York, USA March 2009

  2. Main Points Scheduling-independent message passing works for parallel programming We use the SHIM language This paradigm helps to safely explore schedules Compiler catches race-related bugs Our compiler generates code that runs on the IBM CELL Synthesizing communication the trick

  3. A SHIM example Five functions that call each void main () { other and communicate try { through channel A chan int A ; f( A ); par g( A ); } catch ( Done ) {} } void g( chan int A ) { void f( chan int & A ) throws Done { recv A; h( A ); par j( A ); recv A; } } void h( chan int & A ) { void j( chan int A ) throws Done { A = 4 ; send A; recv A; A = 2 ; send A; throw Done; } }

  4. A SHIM example Parents call children void main () { try { chan int A ; f( A ); par g( A ); } catch ( Done ) {} } void g( chan int A ) { void f( chan int & A ) throws Done { recv A; h( A ); par j( A ); recv A; } } void h( chan int & A ) { void j( chan int A ) throws Done { A = 4 ; send A; recv A; A = 2 ; send A; throw Done; } }

  5. A SHIM example h sends 4 on A , void main () { g and j rendezvous try { chan int A ; f( A ); par g( A ); } catch ( Done ) {} } void g( chan int A ) { void f( chan int & A ) throws Done { recv A; h( A ); par j( A ); recv A; } } void h( chan int & A ) { void j( chan int A ) throws Done { A = 4 ; send A; recv A; A = 2 ; send A; throw Done; } }

  6. A SHIM example j throws an exception. g and void main () { h poisoned by attempting try { communication chan int A ; f( A ); par g( A ); } catch ( Done ) {} } void g( chan int A ) { void f( chan int & A ) throws Done { recv A; h( A ); par j( A ); recv A; } } void h( chan int & A ) { void j( chan int A ) throws Done { A = 4 ; send A; recv A; A = 2 ; send A; throw Done; } }

  7. A SHIM example Concurrent processes void main () { terminate, control passed to try { exception handler chan int A ; f( A ); par g( A ); } catch ( Done ) {} } void g( chan int A ) { void f( chan int & A ) throws Done { recv A; h( A ); par j( A ); recv A; } } void h( chan int & A ) { void j( chan int A ) throws Done { A = 4 ; send A; recv A; A = 2 ; send A; throw Done; } }

  8. Task and Channel Structures void foo ( int a , int a ) { chan int c ; }

  9. A } state; Task and Channel Structures void foo ( int a , int a ) { struct { chan int c ; } pthread_t ≀ ; YIELD ; pthread_mutex_t ; pthread_cond_t enum { ! , , int children; /* xxx */ int a; /* formal */ int b; /* formal */ } thread_foo;

  10. A } state; Task and Channel Structures � � void foo ( int a , int a ) { � struct { chan int c ; } A pthread_t ≀ ; � YIELD ; pthread_mutex_t ; pthread_cond_t struct { enum { ! , YIELD ; , pthread_mutex_t ; int children; /* xxx */ pthread_cond_t int a; /* formal */ uint connected; /* */ int b; /* formal */ uint blocked; /* ! */ } thread_foo; uint poisoned /* */ int * ; } channel_c;

  11. A } state; Task and Channel Structures � � void foo ( int a , int a ) { � struct { chan int c ; } A pthread_t ≀ ; � YIELD ; pthread_mutex_t ; pthread_cond_t struct { enum { ! , YIELD ; , pthread_mutex_t ; int children; /* xxx */ pthread_cond_t int a; /* formal */ uint connected; /* */ int b; /* formal */ uint blocked; /* ! */ } thread_foo; uint poisoned /* */ int * ; } channel_c; void event_c () { if ( c . connected == c . blocked ) { // Communicate } else if ( c . poisoned ) { // Propagate exceptions } }

  12. Pthreads Implementation void main () { struct { ... } _task_main ; try { void _func_main () { ... } // Code for task main chan int A ; f ( A ); par g ( A ); struct { ... } _chan_A ; } catch ( Done ) {} void _event_A () { ... } // Synchronize on A } void f ( chan int & A ) throws Done { struct { ... } _task_f ; h ( A ); par j ( A ); void _func_f () { // Code for task f } } void g ( chan int A ) { struct { ... } _task_g ; recv A ; void _func_g () { → recv A ; // Code for task g } } void h ( chan int & A ) { struct { ... } _task_h ; A = 4 ; send A ; void _func_h () { A = 2 ; send A ; // Code for task h } } void j ( chan int A ) throws Done { struct { ... } _task_j ; recv A ; void _func_j () { throw Done ; // Code for task j } }

  13. IBM’s Cell Broadband Engine

  14. 512K L2 512K L2 SPE SPE SPE SPE SPE SPE SPE SPE 256K 256K 256K 256K 256K 256K 256K 256K IBM’s Cell Broadband Engine SPE SPE SPE SPE SPE SPE SPE SPE PPE PPE 256K 256K 256K 256K 256K 256K 256K 256K

  15. 512K L2 512K L2 SPE SPE SPE SPE SPE SPE SPE SPE 256K 256K 256K 256K 256K 256K 256K 256K 128 bits → 128 bits → 128 bits ← IBM’s Cell Broadband Engine 128 bits ← Element Inter onne t Bus Element Inter onne t Bus SPE SPE SPE SPE SPE SPE SPE SPE PPE PPE 256K 256K 256K 256K 256K 256K 256K 256K

  16. Adapting Pthreads Code to the Cell struct { ... } _task_main ; void _func_main () { ... } // Code for main struct { ... } _chan_A ; void _event_A () { ... } // Synchronize on A struct { ... } _task_f ; void _func_f () { // Code for task f } struct { ... } _task_g ; void _func_g () { // Code for task g } struct { ... } _task_h ; void _func_h () { // Code for task h } struct { ... } _task_j ; void _func_j () { // Code for task j }

  17. Adapting Pthreads Code to the Cell PPE Code struct { ... } _task_main ; void _func_main () { ... } // Code for main struct { ... } _chan_A ; On SPE 1 void _event_A () { ... } // Synchronize on A struct { ... } _task_h ; struct { ... } _task_f ; void _func_f () { void main () { // Code for task f // Code for task h } } struct { ... } _task_g ; void _func_g () { // Code for task g } On SPE 2 struct { ... } _task_h ; struct { ... } _task_j ; void _func_h () { // Proxy for task h void main () { } // Code for task j } struct { ... } _task_j ; void _func_j () { // Proxy for task j }

  18. Communication Details struct { int A ; } _task_j ; void j ( chan int A ) throws Done { recv A ; void main () { // Code for task j throw Done ; for (;;) { } if ( mailbox () == EXIT ) return ; struct { DMA_receive ( _task_j . A ); ... mailbox_send ( BLOCK_A ); int A ; if ( mailbox () == POISON ) } _task_j ; break ; DMA_receive ( _task_j . A ); void _func_j () { // j’s proxy mailbox_send ( POISON ); mailbox_send ( START ); } for (;;) { } switch ( mailbox ()) { case BLOCK_A : _chan_A . _blocked |= h ; _event_A (); while ( _chan_A . blocked & h ) wait ( _chan_A . _cond ); mailbox_send ( ACK ); break ; case TERM : ... case POISON : ... } } }

  19. Communication Details struct { int A ; } _task_j ; void j ( chan int A ) throws Done { recv A ; void main () { // Code for task j throw Done ; for (;;) { } if ( mailbox () == EXIT ) return ; struct { DMA_receive ( _task_j . A ); ... mailbox_send ( BLOCK_A ); int A ; if ( mailbox () == POISON ) } _task_j ; break ; DMA_receive ( _task_j . A ); void _func_j () { // j’s proxy mailbox_send ( POISON ); mailbox_send ( START ); } for (;;) { } switch ( mailbox ()) { case BLOCK_A : _chan_A . _blocked |= h ; Proxy wakes SPE 1 _event_A (); while ( _chan_A . blocked & h ) wait ( _chan_A . _cond ); mailbox_send ( ACK ); break ; case TERM : ... case POISON : ... } } }

  20. Communication Details struct { int A ; } _task_j ; void j ( chan int A ) throws Done { recv A ; void main () { // Code for task j throw Done ; for (;;) { } if ( mailbox () == EXIT ) return ; struct { DMA_receive ( _task_j . A ); ... mailbox_send ( BLOCK_A ); int A ; if ( mailbox () == POISON ) } _task_j ; break ; DMA_receive ( _task_j . A ); void _func_j () { // j’s proxy mailbox_send ( POISON ); mailbox_send ( START ); } for (;;) { } switch ( mailbox ()) { case BLOCK_A : _chan_A . _blocked |= h ; Proxy wakes SPE 1 _event_A (); while ( _chan_A . blocked & h ) SPE DMAs arguments 2 wait ( _chan_A . _cond ); mailbox_send ( ACK ); break ; case TERM : ... case POISON : ... } } }

  21. Communication Details struct { int A ; } _task_j ; void j ( chan int A ) throws Done { recv A ; void main () { // Code for task j throw Done ; for (;;) { } if ( mailbox () == EXIT ) return ; struct { DMA_receive ( _task_j . A ); ... mailbox_send ( BLOCK_A ); int A ; if ( mailbox () == POISON ) } _task_j ; break ; DMA_receive ( _task_j . A ); void _func_j () { // j’s proxy mailbox_send ( POISON ); mailbox_send ( START ); } for (;;) { } switch ( mailbox ()) { case BLOCK_A : _chan_A . _blocked |= h ; Proxy wakes SPE 1 _event_A (); while ( _chan_A . blocked & h ) SPE DMAs arguments 2 wait ( _chan_A . _cond ); mailbox_send ( ACK ); SPE blocks on A, notifies proxy 3 break ; case TERM : ... case POISON : ... } } }

  22. Communication Details struct { int A ; } _task_j ; void j ( chan int A ) throws Done { recv A ; void main () { // Code for task j throw Done ; for (;;) { } if ( mailbox () == EXIT ) return ; struct { DMA_receive ( _task_j . A ); ... mailbox_send ( BLOCK_A ); int A ; if ( mailbox () == POISON ) } _task_j ; break ; DMA_receive ( _task_j . A ); void _func_j () { // j’s proxy mailbox_send ( POISON ); mailbox_send ( START ); } for (;;) { } switch ( mailbox ()) { case BLOCK_A : _chan_A . _blocked |= h ; Proxy wakes SPE 1 _event_A (); while ( _chan_A . blocked & h ) SPE DMAs arguments 2 wait ( _chan_A . _cond ); mailbox_send ( ACK ); SPE blocks on A, notifies proxy 3 break ; case TERM : ... Proxy communicates, notifies SPE 4 case POISON : ... } } }

Recommend


More recommend