Difference between revisions of "GPU621/Chapel"

From CDOT Wiki
Jump to: navigation, search
(Basic)
(Sync/Singles)
Line 129: Line 129:
 
*The readXX() method, defined for sync and single variables, returns the value of the variable regardless of the state.  
 
*The readXX() method, defined for sync and single variables, returns the value of the variable regardless of the state.  
 
*The writeFF() method, defined for sync variables, blocks until the state is full and then and then assigns the value argument to the variable.
 
*The writeFF() method, defined for sync variables, blocks until the state is full and then and then assigns the value argument to the variable.
 +
 
=== Locales ===
 
=== Locales ===
 
In Chapel, the locale type refers to a unit of the machine resources on which your program is running. Locales have the capability to store variables and to run Chapel tasks.
 
In Chapel, the locale type refers to a unit of the machine resources on which your program is running. Locales have the capability to store variables and to run Chapel tasks.

Revision as of 23:55, 29 November 2022

Introduction

The Chapel is an open-source programming language designed for productive parallel computing at scale. The Chapel compiler is written in C and C++14. The backend is LLVM, written in C++. The goal of Chapel is to improve the programmability of parallel computers in general.

Installation

Basic

Variables

Variables are declared with the var keyword. Variable declarations must have a type, initializer, or both.

     var myVariable1: int;
     writeln("myVariable1 = ", myVariable1);

const and param can be used to declare runtime constants and compile-time constants respectively. A const must be initialized in place, but can have its value generated at runtime. A param must be known at compile time.

     const myConst: real = sqrt(myVariable2);
     param myParam = 3.14;
     writeln("myConst = ", myConst, ", myParam = ", myParam);

At module scope, all three variable kinds can be qualified by the config keyword. This allows the initial value to be overridden on the command line. A config var or config const may be overridden when the program is executed; a config param may be overridden when the program is compiled. Similarly, type aliases maybe be qualified by the config keyword. The comment following each declaration shows how the value can be modified.

     config var cfgVar = "hello";         // ./variables --cfgVar="world"
     config const cfgConst: bool = false; // ./variables --cfgConst=true
     config param cfgParam = 4;           // chpl variables.chpl -s cfgParam=1
     config type cfgType = complex;       // chpl variables.chpl -s cfgType=imag
     writeln("cfgVar = ", cfgVar,
             ", cfgConst = ", cfgConst,
             ", cfgParam = ", cfgParam,
             ", cfgType = ", cfgType:string);

Procedure

The procedures includes overloading, argument intents and dynamic dispatch.

Overloading

The Chapel allows the user to do the overload function and overload operators.

Argument Intents

Normal (default) intent means that a formal argument cannot be modified in the body of a procedure.

  • To allow changing the formal (but not the actual), use the in intent
  • The inout intent will write back the final value of a formal parameter when the procedure exits.
  • Similar to the inout intent, the ref intent causes the value of the actual to change depending on the function. However, while the inout copies the argument in upon entering the function and copies the new value out upon exiting, using a ref intent causes any updates to the formal to immediately affect the call site.
  • The out intent causes the actual argument to be ignored when the procedure starts. The actual is assigned the value of the corresponding formal when the routine exits.

Class

Like C++, the Chapel allows the user to create a new type that can contain variables and constants, called fields, as well as functions and iterators called methods. A new class type is declared using the class keyword.

   class C {
     var a, b: int;
     proc printFields() {
       writeln("a = ", a, " b = ", b);
     }
   }

Record

A record type can be declared using the record keyword. A record is a type that can contain variables and constants, called fields, as well as functions and iterators called methods. Records have many similarities to classes, but there are several important differences:

  • Records do not support inheritance and virtual dispatch
  • Record variables refer to distinct memory
  • copy-initialization and assignment can be implemented for records
   record Color {
     var red: uint(8);
     var green: uint(8);
     var blue: uint(8);
   }

Special Methods

  • An initializer named init is called when creating an instance of the class or record.
  • A method named init= is called a copy initializer and accepts a single argument.
  • If a method named postinit that accepts zero arguments exists for a class or record type, it will automatically be called after the initializer call completes.
  • The deinit method will deinitialize a record when it leaves scope, or a class when delete is called on it.
  • The this method gives the record the ability to be accessed like an array.
  • An iterator named these that can accept zero arguments is automatically called when a record or class instance is used in the iterator position of a for loop.
  • The writeThis and readThis methods allows user to read or write the instance.

Nothing Variable

A nothing is removed by the compiler and doesn’t exist during program execution. The value none has type nothing and can be assigned to a nothing variable, or returned from a function with nothing return type.

   var nothingVar: nothing;

The value none is the only value of the nothing type.

   var nothingVar2 = none;

The following (commented out) statements are compile time errors:

   nothingVar = 1;

Parallel Iterators

Chapel has two main types of parallel iterators:

  • Standalone parallel iterators are the simpler form and can be used to define parallelism for a simple forall loop.
  iter fibonacci(n: int): int {
     var i1 = 0, i2 = 1;
     for i in 1..#n {
        yield i1;
        var i3 = i1 + i2;
        i1 = i2;
        i2 = i3;
     }
  }
  config const n =10;
  for (i,idVar) in zip(0..n, fibonacci(n)) do
     writeln("#", i, " - ", idVar);
  • Leader-follower iterators are a more involved form that support zippered forall loops.
  forall (a, b, c) in zip(A, B, C) do
     //in here, A is the leader; and A, B, C is followers

Task Parallelism

Chapel’s parallel tasking features, namely the begin, cobegin, and coforall statements.

  • The begin statement spawns a thread of execution that is independent of the current (main) thread of execution.
   writeln("1: ### The begin statement ###");
  • The cobegin statement can be used to spawn a block of tasks, one for each statement.
   writeln("2: ### The cobegin statement ###");
   cobegin {
     writeln("2: output from spawned task 1");
     writeln("2: output from spawned task 2");
   }
  • This loop form is like a for loop in which each iteration of the loop is executed by a distinct task.
   writeln("4: ### The coforall loop ###");
   coforall i in 1..n {
     writeln("4: output from spawned task 1 (iteration ", i, ")");
     writeln("4: output from spawned task 2 (iteration ", i, ")");
   }

Sync/Singles

Sync and single are type qualifiers that can be applied to all Chapel primitive types except strings and complex. Sync and single variables have an associated state that is either full or empty. Single variables are sync variables that can only be written once. If a sync or single variable is declared with an initializing expression, its state is set to full and its value is that of the expression. Without an initializing expression, a sync or single variable’s state is set to empty and its value is the default value for the base type.

   config const n = 7;
   var sy$: sync int=1;  // state = full, value = 1
   var si$: single bool; // state = empty, value = false

The methods defined on sync / single variables:

  • The reset() method, defined for sync variables, sets the value of the variable to the default value for the type and the state to empty.
  • The isFull method returns true if the sync or single variable is in the full state, false otherwise.
  • The writeEF() method, defined for sync and single variables, blocks until the state is empty and then assigns the value argument to the variable and then sets the state to full.
  • The readFE() method, defined for sync variables, blocks until the state is full and then reads the value of the variable, sets the state to empty, and then returns the value.
  • The readFF() method, defined for sync and single variables, blocks until the state is full and then reads the value of the variable and returns the value.
  • The writeXF() method, defined for sync variables, assigns the value argument to the variable and then sets the state to full
  • The readXX() method, defined for sync and single variables, returns the value of the variable regardless of the state.
  • The writeFF() method, defined for sync variables, blocks until the state is full and then and then assigns the value argument to the variable.

Locales

In Chapel, the locale type refers to a unit of the machine resources on which your program is running. Locales have the capability to store variables and to run Chapel tasks.

Reference