diff options
| author | ven <vendethiel@hotmail.fr> | 2015-08-02 23:44:50 +0200 | 
|---|---|---|
| committer | ven <vendethiel@hotmail.fr> | 2015-08-02 23:44:50 +0200 | 
| commit | 1f6f7b784345a7224fef64bc27db206a0946b366 (patch) | |
| tree | 5f04bd80c7980f3feea8d2ce4c622bc2061108ec | |
| parent | 28ce62ef7e68add0277044fe030e0541436a0a6f (diff) | |
| parent | 11ca1012e402bbc51f70283c4e20ee8bf31deb7f (diff) | |
Merge pull request #1177 from ian-bertolacci/master
Chapel: Sync, atomics, reductions, scans, zippered iterators
| -rw-r--r-- | chapel.html.markdown | 173 | 
1 files changed, 158 insertions, 15 deletions
diff --git a/chapel.html.markdown b/chapel.html.markdown index 53e9747c..cfde0454 100644 --- a/chapel.html.markdown +++ b/chapel.html.markdown @@ -32,10 +32,10 @@ stderr.writeln( "This goes to standard error" );  var myVar = 10; // 10 is an int, so myVar is implicitly an int  myVar = -10;  var mySecondVar = myVar; -// var anError; // this would be a compile time error. +// var anError; // this would be a compile-time error.  // We can (and should) explicitly type things -var myThirdVar: real; // define mySecondVar as a real +var myThirdVar: real;  var myFourthVar: real = -1.234;  myThirdVar = myFourthVar; @@ -57,24 +57,24 @@ var my64Real: real(64) = 1.516; // 64 bit (8 bytes) sized real  var intFromReal = myReal : int;  var intFromReal2: int = myReal : int; -// consts are constants, they cannot be changed after set in runtime +// consts are constants, they cannot be changed after set in runtime.  const almostPi: real = 22.0/7.0; -// params are constants whose value must be known statically at compile time -// Like consts, they cannot be changed during runtime +// params are constants whose value must be known statically at compile-time +// Their value cannot be changed.  param compileTimeConst: int = 16;  // The config modifier allows values to be set at the command line -// and is much easier that the usual getOpts debacle  +// and is much easier than the usual getOpts debacle   // config vars and consts can be changed through the command line at run time  config var varCmdLineArg: int = -123;   config const constCmdLineArg: int = 777;  // Set with --VarName=Value or --VarName Value at run time -// config params can be set at compile time +// config params can be set/changed at compile-time  config param paramCmdLineArg: bool = false; +// Set config with --set paramCmdLineArg=value at compile-time  writeln( varCmdLineArg, ", ", constCmdLineArg, ", ", paramCmdLineArg ); -// Set config with --set paramCmdLineArg=value at compile time  // refs operate much like a reference in C++  var actual = 10; @@ -465,7 +465,7 @@ genericProc( 1.0+2.0i, 3.0+4.0i );  // We can also enforce a form of polymorphism with the 'where' clause  // This allows the compiler to decide which function to use. -// Note: that means that all information needs to be known at compile time.  +// Note: that means that all information needs to be known at compile-time.   // The param modifier on the arg is used to enforce this constraint.  proc whereProc( param N : int ): void   where ( N > 0 ) { @@ -501,7 +501,7 @@ writeln( false ^ true  );  writeln( true  ^ false );  writeln( false ^ false ); -// Define a * operator on any two types that returns a tupe of those types +// Define a * operator on any two types that returns a tuple of those types  proc *( left : ?ltype, right : ?rtype): ( ltype, rtype ){    return (left, right );  } @@ -533,6 +533,14 @@ iter oddsThenEvens( N: int ): int {  for i in oddsThenEvens( 10 ) do write( i, ", " );  writeln( ); +// We can zipper together two or more iterators (who have the same number  +// of iterations)  using zip() to create a single zipped iterator, where each  +// iteration of the zipped iterator yields a tuple of one value yielded  +// from each iterator. +                                 // Ranges have implicit iterators +for (positive, negative) in zip( 1..5, -5..-1) do  +  writeln( (positive, negative) ); +  // Classes are similar to those in C++ and Java.  // They currently lack privatization  class MyClass { @@ -569,7 +577,7 @@ class MyClass {    }  } - +    // Construct using default constructor, using default values  var myObject = new MyClass( 10 );      myObject = new MyClass( memberInt = 10 ); // Equivalent @@ -732,6 +740,7 @@ writeln( );  use Time; // Import the Time module to use Timer objects  var timer: Timer;   var myBigArray: [{1..4000,1..4000}] real; // Large array we will write into +  // Serial Experiment  timer.start( ); // Start timer  for (x,y) in myBigArray.domain { // Serial iteration @@ -754,9 +763,144 @@ timer.clear( );  // A succinct way of writing a forall loop over an array:  // iterate over values -[ val in myBigArray ] val = 1 / val;  +[ val in myBigArray ] val = 1 / val; +  // or iterate over indicies  [ idx in myBigArray.domain ] myBigArray[idx] = -myBigArray[idx];  + +proc countdown( seconds: int ){ +  for i in 1..seconds by -1 { +    writeln( i ); +    sleep( 1 ); +  } +} + +// Atomic variables, common to many languages, are ones whose operations +// occur uninterupted. Multiple threads can both modify atomic variables +// and can know that their values are safe. +// Chapel atomic variables can be of type bool, int, uint, and real. +var uranium: atomic int; +uranium.write( 238 );      // atomically write a variable +writeln( uranium.read() ); // atomically read a variable + +// operations are described as functions, you could define your own operators. +uranium.sub( 3 ); // atomically subtract a variable +writeln( uranium.read() ); + +var replaceWith = 239; +var was = uranium.exchange( replaceWith );  +writeln( "uranium was ", was, " but is now ", replaceWith ); + +var isEqualTo = 235; +if uranium.compareExchange( isEqualTo, replaceWith ) { +  writeln( "uranium was equal to ", isEqualTo,  +           " so replaced value with ", replaceWith ); +} else { +  writeln( "uranium was not equal to ", isEqualTo,  +           " so value stays the same...  whatever it was" ); +} + +sync { +  begin { // Reader task +    writeln( "Reader: waiting for uranium to be ", isEqualTo ); +    uranium.waitFor( isEqualTo ); +    writeln( "Reader: uranium was set (by someone) to ", isEqualTo ); +  } + +  begin { // Writer task +    writeln( "Writer: will set uranium to the value ", isEqualTo, " in..." ); +    countdown( 3 ); +    uranium.write( isEqualTo ); +  } +} + +// sync vars have two states: empty and full. +// If you read an empty variable or write a full variable, you are waited +// until the variable is full or empty again +var someSyncVar$: sync int; // varName$ is a convention not a law. +sync { +  begin { // Reader task +    writeln( "Reader: waiting to read." ); +    var read_sync = someSyncVar$; +    writeln( "value is ", read_sync ); +  } + +  begin { // Writer task +    writeln( "Writer: will write in..." ); +    countdown( 3 ); +    someSyncVar$ = 123;     +  } +} + +// single vars can only be written once. A read on an unwritten single results +// in a wait, but when the variable has a value it can be read indefinitely +var someSingleVar$: single int; // varName$ is a convention not a law. +sync { +  begin { // Reader task +    writeln( "Reader: waiting to read." ); +    for i in 1..5 { +      var read_single = someSingleVar$; +      writeln( "Reader: iteration ", i,", and the value is ", read_single ); +    } +  } + +  begin { // Writer task +    writeln( "Writer: will write in..." ); +    countdown( 3 ); +    someSingleVar$ = 5; // first and only write ever. +  } +} + +// Heres an example of using atomics and a synch variable to create a  +// count-down mutex (also known as a multiplexer) +var count: atomic int; // our counter +var lock$: sync bool;   // the mutex lock + +count.write( 2 );       // Only let two tasks in at a time. +lock$.writeXF( true );  // Set lock$ to full (unlocked) +// Note: The value doesnt actually matter, just the state  +// (full:unlocked / empty:locked) +// Also, writeXF() fills (F) the sync var regardless of its state (X) + +coforall task in 1..#5 { // Generate tasks +  // Create a barrier +  do{ +    lock$;                 // Read lock$ (wait) +  }while count.read() < 1; // Keep waiting until a spot opens up +   +  count.sub(1);          // decrement the counter +  lock$.writeXF( true ); // Set lock$ to full (signal) +   +  // Actual 'work' +  writeln( "Task #", task, " doing work." ); +  sleep( 2 ); + +  count.add( 1 );        // Increment the counter +  lock$.writeXF( true ); // Set lock$ to full (signal) +} + +// we can define the operations + * & | ^ && || min max minloc maxloc +// over an entire array using scans and reductions +// Reductions apply the operation over the entire array and +// result in a single value +var listOfValues: [1..10] int = [15,57,354,36,45,15,456,8,678,2]; +var sumOfValues = + reduce listOfValues; +var maxValue = max reduce listOfValues; // 'max' give just max value + +// 'maxloc' gives max value and index of the max value +// Note: We have to zip the array and domain together with the zip iterator +var (theMaxValue, idxOfMax) = maxloc reduce zip(listOfValues,  +                                                listOfValues.domain); +                                                 +writeln( (sumOfValues, maxValue, idxOfMax, listOfValues[ idxOfMax ] ) ); + +// Scans apply the operation incrementally and return an array of the +// value of the operation at that index as it progressed through the  +// array from array.domain.low to array.domain.high +var runningSumOfValues = + scan listOfValues; +var maxScan = max scan listOfValues; +writeln( runningSumOfValues ); +writeln( maxScan );  ```  Who is this tutorial for? @@ -771,12 +915,10 @@ Occasionally check back here and on the [Chapel site](http://chapel.cray.com) to  ### What this tutorial is lacking:   * Modules and standard modules - * Synchronize variables and atomic operations   * Multiple Locales (distributed memory system)   * ```proc main(){ ... }```   * Records   * Whole/sliced array assignment - * Reductions and scans   * Range and domain slicing   * Parallel iterators @@ -817,6 +959,7 @@ Builds like other compilers:  ```chpl myFile.chpl -o myExe``` -A notable argument: +Notable arguments:   * ``--fast``: enables a number of optimizations and disables array bounds checks. Should only enable when application is stable. + * ```--set <Symbol Name>=<Value>```: set config param <Symbol Name> to <Value> at compile-time  | 
