From 155bf5d0a285de2c4dec4033c8e9c20f6a42072b Mon Sep 17 00:00:00 2001 From: Ian Bertolacci Date: Sun, 19 Jul 2015 19:59:30 -0700 Subject: Added sync, single, and atomic vars. --- chapel.html.markdown | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/chapel.html.markdown b/chapel.html.markdown index 7ac73bbb..4f857775 100644 --- a/chapel.html.markdown +++ b/chapel.html.markdown @@ -757,6 +757,83 @@ timer.clear( ); [ 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 ); + } +} + +// 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 { + writeln( "Waiting to read" ); + var read_sync = someSyncVar$; + writeln( "value is ", read_sync ); + } + + begin { + writeln( "Writing 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 { + writeln( "Waiting to read" ); + for i in 1..5 { + var read_single = someSingleVar$; + writeln( i,"th time around an the value is ", read_single ); + } + } + + begin { + writeln( "Writing in..." ); + countdown( 3 ); + someSingleVar$ = 5; // first and only write ever. + } +} + +// atomic variables can be of type bool, int, uint, and real of any size. +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, + " value stays the same... whatever it was" ); +} + +sync { + begin { + writeln( "Waiting to for uranium to be ", isEqualTo ); + uranium.waitFor( isEqualTo ); + writeln( "Uranium was set (by someone) to ", isEqualTo ); + } + + begin { + writeln( "Waiting to write uranium to ", isEqualTo ); + countdown( 3 ); + uranium.write( isEqualTo ); + } +} ``` Who is this tutorial for? @@ -771,7 +848,6 @@ 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 -- cgit v1.2.3 From bcc84f9c768041b7f260907d4432e12658b76626 Mon Sep 17 00:00:00 2001 From: Ian Bertolacci Date: Mon, 20 Jul 2015 08:09:28 -0700 Subject: Explained atomics, moved atomics first Felt the need to add in an explanation about atomics, then felt that (because atomics are common in language and in theory) it should go before sync and single vars. Should I explain sync and single? --- chapel.html.markdown | 69 +++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/chapel.html.markdown b/chapel.html.markdown index 6fe7c1b0..bbbf50e8 100644 --- a/chapel.html.markdown +++ b/chapel.html.markdown @@ -765,6 +765,42 @@ proc countdown( seconds: int ){ } } +// 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, + " value stays the same... whatever it was" ); +} + +sync { + begin { + writeln( "Waiting to for uranium to be ", isEqualTo ); + uranium.waitFor( isEqualTo ); + writeln( "Uranium was set (by someone) to ", isEqualTo ); + } + + begin { + writeln( "Waiting to write uranium to ", isEqualTo ); + 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 @@ -801,39 +837,6 @@ sync { someSingleVar$ = 5; // first and only write ever. } } - -// atomic variables can be of type bool, int, uint, and real of any size. -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, - " value stays the same... whatever it was" ); -} - -sync { - begin { - writeln( "Waiting to for uranium to be ", isEqualTo ); - uranium.waitFor( isEqualTo ); - writeln( "Uranium was set (by someone) to ", isEqualTo ); - } - - begin { - writeln( "Waiting to write uranium to ", isEqualTo ); - countdown( 3 ); - uranium.write( isEqualTo ); - } -} ``` Who is this tutorial for? -- cgit v1.2.3 From d2d98a381047d30e0355a8dacd0fdbe1188345c0 Mon Sep 17 00:00:00 2001 From: Ian Bertolacci Date: Mon, 20 Jul 2015 08:17:01 -0700 Subject: Spelling error Tupe -> Tuple --- chapel.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapel.html.markdown b/chapel.html.markdown index bbbf50e8..9ce184c0 100644 --- a/chapel.html.markdown +++ b/chapel.html.markdown @@ -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 ); } -- cgit v1.2.3 From 2936ca4c69f7b96dfbe7f67de0ebcad910395ba1 Mon Sep 17 00:00:00 2001 From: Ian Bertolacci Date: Mon, 20 Jul 2015 12:59:35 -0700 Subject: Erroneous comment removed "define mySecondVar as a real" unnecessary and incorrect. --- chapel.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapel.html.markdown b/chapel.html.markdown index 9ce184c0..4cbc5a4b 100644 --- a/chapel.html.markdown +++ b/chapel.html.markdown @@ -35,7 +35,7 @@ var mySecondVar = myVar; // 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; -- cgit v1.2.3 From d35d9d213c3ce3ba1bb53aef896898d87e213d58 Mon Sep 17 00:00:00 2001 From: Ian Bertolacci Date: Mon, 20 Jul 2015 13:01:25 -0700 Subject: Word error that -> than --- chapel.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapel.html.markdown b/chapel.html.markdown index 4cbc5a4b..b124f54a 100644 --- a/chapel.html.markdown +++ b/chapel.html.markdown @@ -65,7 +65,7 @@ const almostPi: real = 22.0/7.0; 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; -- cgit v1.2.3 From 77daaef8ed6d2fed88405cf038d4e5f0b82dc1ef Mon Sep 17 00:00:00 2001 From: Ian Bertolacci Date: Mon, 20 Jul 2015 13:07:23 -0700 Subject: config param changeup changed some of the wording of the param config example. Namely put the comment immediately below the example. Also added --set to the noteable arguments list. Also changed "compile(?: )?time" to "compile-time" --- chapel.html.markdown | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/chapel.html.markdown b/chapel.html.markdown index b124f54a..520f959d 100644 --- a/chapel.html.markdown +++ b/chapel.html.markdown @@ -32,7 +32,7 @@ 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; @@ -57,11 +57,11 @@ 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 @@ -71,10 +71,10 @@ 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 ) { @@ -896,6 +896,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 =```: set config param to at compile-time -- cgit v1.2.3 From 3332ce43bb73dcb850250847c6cffdc396338d5e Mon Sep 17 00:00:00 2001 From: Ian Bertolacci Date: Wed, 22 Jul 2015 19:08:22 -0700 Subject: added scans and reductions --- chapel.html.markdown | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/chapel.html.markdown b/chapel.html.markdown index 520f959d..e058bde9 100644 --- a/chapel.html.markdown +++ b/chapel.html.markdown @@ -837,6 +837,25 @@ sync { someSingleVar$ = 5; // first and only write ever. } } + +// 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 = [456,354,15,57,36,45,15,8,678,2]; +var sumOfValues = + reduce listOfValues; +var maxValue = max reduce listOfValues; // give just max value +// gives max value and index of the max value +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? -- cgit v1.2.3 From c2f85b27b5620054bb0306ee4730cefff60ad87c Mon Sep 17 00:00:00 2001 From: Ian Bertolacci Date: Sat, 1 Aug 2015 17:02:51 -0700 Subject: added count-down mutex example. Cleaned up some of the reductions and scans prints --- chapel.html.markdown | 88 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 23 deletions(-) diff --git a/chapel.html.markdown b/chapel.html.markdown index e058bde9..0d1d38dc 100644 --- a/chapel.html.markdown +++ b/chapel.html.markdown @@ -533,6 +533,12 @@ iter oddsThenEvens( N: int ): int { for i in oddsThenEvens( 10 ) do write( i, ", " ); writeln( ); +// The 'zippered' iterator is an iterator that takes two or more iterators that +// have the same number of iterations and zips them together into one stream + // Ranges have implicit iterators +for (odd, even) in zip( 1..#10 by 2, 2..#10 by 2 ) do + writeln( (odd, even) ); + // Classes are similar to those in C++ and Java. // They currently lack privatization class MyClass { @@ -569,7 +575,7 @@ class MyClass { } } - + // Construct using default constructor, using default values var myObject = new MyClass( 10 ); myObject = new MyClass( memberInt = 10 ); // Equivalent @@ -732,6 +738,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,7 +761,8 @@ 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]; @@ -770,32 +778,35 @@ proc countdown( seconds: int ){ // 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 +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, - " value stays the same... whatever it was" ); + " so value stays the same... whatever it was" ); } sync { - begin { - writeln( "Waiting to for uranium to be ", isEqualTo ); + begin { // Reader task + writeln( "Reader: waiting for uranium to be ", isEqualTo ); uranium.waitFor( isEqualTo ); - writeln( "Uranium was set (by someone) to ", isEqualTo ); + writeln( "Reader: uranium was set (by someone) to ", isEqualTo ); } - begin { - writeln( "Waiting to write uranium to ", isEqualTo ); + begin { // Writer task + writeln( "Writer: will set uranium to the value ", isEqualTo, " in..." ); countdown( 3 ); uranium.write( isEqualTo ); } @@ -806,14 +817,14 @@ sync { // until the variable is full or empty again var someSyncVar$: sync int; // varName$ is a convention not a law. sync { - begin { - writeln( "Waiting to read" ); + begin { // Reader task + writeln( "Reader: waiting to read." ); var read_sync = someSyncVar$; writeln( "value is ", read_sync ); } - begin { - writeln( "Writing in..." ); + begin { // Writer task + writeln( "Writer: will write in..." ); countdown( 3 ); someSyncVar$ = 123; } @@ -823,30 +834,62 @@ sync { // 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 { - writeln( "Waiting to read" ); + begin { // Reader task + writeln( "Reader: waiting to read." ); for i in 1..5 { var read_single = someSingleVar$; - writeln( i,"th time around an the value is ", read_single ); + writeln( "Reader: iteration ", i,", and the value is ", read_single ); } } - begin { - writeln( "Writing in..." ); + 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 = [456,354,15,57,36,45,15,8,678,2]; +var listOfValues: [1..10] int = [15,57,354,36,45,15,456,8,678,2]; var sumOfValues = + reduce listOfValues; -var maxValue = max reduce listOfValues; // give just max value -// gives max value and index of the max value -var (theMaxValue, idxOfMax) = maxloc reduce zip(listOfValues, listOfValues.domain); +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 @@ -874,7 +917,6 @@ Occasionally check back here and on the [Chapel site](http://chapel.cray.com) to * ```proc main(){ ... }``` * Records * Whole/sliced array assignment - * Reductions and scans * Range and domain slicing * Parallel iterators -- cgit v1.2.3 From 11ca1012e402bbc51f70283c4e20ee8bf31deb7f Mon Sep 17 00:00:00 2001 From: Ian Bertolacci Date: Sun, 2 Aug 2015 14:35:41 -0700 Subject: Clarified some wording on the zipper iterator. Changed the example to something more simple and informative. --- chapel.html.markdown | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/chapel.html.markdown b/chapel.html.markdown index 0d1d38dc..cfde0454 100644 --- a/chapel.html.markdown +++ b/chapel.html.markdown @@ -533,11 +533,13 @@ iter oddsThenEvens( N: int ): int { for i in oddsThenEvens( 10 ) do write( i, ", " ); writeln( ); -// The 'zippered' iterator is an iterator that takes two or more iterators that -// have the same number of iterations and zips them together into one stream - // Ranges have implicit iterators -for (odd, even) in zip( 1..#10 by 2, 2..#10 by 2 ) do - writeln( (odd, even) ); +// 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 -- cgit v1.2.3