Ateji PX Samples

Ateji PX contains multiple samples illustrating the different constructs of the language and the supported parallel patterns:

  • Data-flow programming
  • Speculative parallelism
  • Recursive parallelism
  • Task parallelism

The following sections contain some code snippets extracted from the samples. They illustrate multiple language constructs that can be combined to implement all parallel patterns.

Hello World

The classic Hello World example:

public class HelloWorld {

  public static void main(String[] args) {
    [
      || System.out.println("Hello");
      || System.out.println("World");
    ]
  }
}

At execution, this program will either print Hello World or World Hello.

Sine (data-flow programming)

This sample illustrates the data-flow programming model using Ateji PX synchronous channels.

The add() method (line 13) illustrates the use of the ? and ! operators to respectively receive and send a value through a channel: integer values are read from the multiple input channels (line 18) and the sum of these values is sent through the output channel (line 23).

 /**
  * The add method is a node in the graph:
  *   - The operator involved is the addition of the inputs.
  *   - The ingoing arcs are the channels ins[0], ..., ins[n].
  *   - The outgoing arc is the channel out.
  *       
  *  _________________
  *       ins[0]       \
  *  _________________ add _________
  *       ...           /     out
  *  _________________ /
  *       ins[n]   */
 private static void add(Chan out, Chan ... ins) {
  while(true) {
   int result = 0; 
   for(Chan in : ins) {
    // receive values on the ingoing arcs
    in ? int value;
    // add the inputs
    result += value;    
   }
   // send the result on the outgoing arc
   out ! result;
  }
 }

The main() method (line 11) illustrates how values can be produced and consumed in parallel using multiple parallel branches (lines 19 to 23):

  • On lines 19 to 21 three sinusoidal signals are produced.
  • On line 22 the three signals are combined
  • Finally, on line 23 the resulting signal is displayed

  /**
  *  The main method composes five elements according to the following pattern:
  * 
  *  sine ___________  
  *           c1     \
  *  sine __________ add ________ display
  *           c2     /       c
  *  sine __________/
  *           c3
  */
 public static void main(String[] args) {
  // How to create an arc c1 between a sine method and an add method:
  // Create a channel c1 and connect it to the output of sine and to the input of add.
  Chan c1 = new Chan();
  Chan c2 = new Chan();
  Chan c3 = new Chan();
  Chan c  = new Chan();
  [ 
    || sine(20, 100, c1);  // connect c1 to the output of sine
    || sine(15, 50, c2);
    || sine(18, 80, c3);
    || add(c, c1, c2, c3); // connect c1 to the input of add
    || display(230, c);
  ]  
}

Sort (speculation)

This sample illustrates how some computations can be speculated: multiple computations are started in parallel and the first branch to complete terminates the enclosing parallel block.

The speculativeSort() function (line 8) contains two parallel branches (lines 18 and 19) containing each a different implementation of the sort algorithm. Both computations are started in parallel and the most efficient implementation (which may depend on the input data) triggers the completion of all other parallel branches.

/**
  * Two sorting algorithms are run in parallel. The first to complete returns
  * the final result.
  * 
  * It is impossible to know which algorithm will return the result.
  * Nevertheless, the value returned by speculativeSort is deterministic.
  */
private static int[] speculativeSort(int[] array)	{
	// Run in parallel both algorithms.
	// The first algorithm to finish will execute a 'return' statement,
	// which will stop the other algorithm and then return its result.
	[
	  // We do not want to use the default implementation for this parallel
	  // composition, because the default implementation is very unfair.
	  // For the speculative parallelism to work, some degree of fairness
	  // is needed.
	  // This is achieved by using the '#(Threads())' indication.		  
	 	|| (#Thread()) return bubbleSortAlgorithm(array);
	 	|| (#Thread()) return insertionSortAlgorithm(array);		 	
	]		
}

Bang

A bang operator (line 13) is a construct allowing to dynamically create new branches in response to a message reception.

void run() {
	[
	 	// ||* is a replication operator (also called bang). It may be seen
	 	// as a process which always creates new branches. As a typical
	 	// example, bang models a network service.
		// 
		// In Ateji PX, to control the number of created branches, a bang is
	 	// bound to a message exchange. 
		// 
		// Here the function waits for new queries and replies to them in
	 	// parallel.
	 	//
	 	||* queryChannel ? Query query :		 		
	 		work(query);
	]
}

Comprehensions

Ateji PX supports built-in comprehensions that can be used both sequentially (lines 3, 9, 15, 21, 27, 33) and in parallel (lines 5, 11, 17, 23, 29).

public static void main(String[] args) {		
	// Computes the sum of all elements in the given data.	   
	int sum = `+ for (int d : data) d;
	System.out.println("sum = " + sum);
	int parallelSum = `+ for || (int d : data) d;
	System.out.println("parallelSum = " + parallelSum);

	// Filter the element in the given data that are more than 10
	Set flat = Monoids.hashSet() for (int d : data, if ( d >= 10)) d;
	System.out.println("flat = " + flat);
	Set parallelFlat = Monoids.hashSet() for || (int d : data, if ( d >= 10)) d;
	System.out.println("parallelFlat = " + parallelFlat);

	// Count of elements in the given data that are equal to 100.
	int count = `+ for (int d : data, if (d == 100) ) 1;
	System.out.println("count = " + count);
	int parallelCount = `+ for || (int d : data, if (d == 100)) 1;
	System.out.println("parallelCount = " + parallelCount);

	// some is true iff *some* element of the data is true
	boolean some = `| for (boolean x : booleanData) x;
	System.out.println("some = " + some);
	boolean parallelSome = `| for || (boolean x : booleanData) x;
	System.out.println("parallelSome = " + parallelSome);

	// Computes the minimum of all elements in the given data.
	Integer min = Monoids.min() for (int x : data) x;
	System.out.println("parallelMin = " + min);
	Integer parallelMin = Monoids.min() for || { x | int x : data };
	System.out.println("parallelMin = " + parallelMin);
		
	// Filter the value in the given map that are more than 10.
	Set otherFilterMap = Monoids.hashSet() for (int v : map.values(), if (v>=10)) v;
	System.out.println("otherFilterMap = " + otherFilterMap);		
}

 

SEO by AceSEF

Customer Quotes

 

We just completed an evaluation of Ateji's product, and it does everything it promises… this is a very smart idea

Martin Curley,
European Research Director,
Intel

 

Ateji PX allows quicker and easier Java parallel programming without several of the pain-points of multithreading coming in the way

Dr. Gourab Nath,
Sr. Research Scientist,

Amadeus

 

Ateji PX is a dream for Java™ developers, enabling all kinds of applications to take better advantage of NVIDIA’s multicore processors.

Stephen Jones,
Product Line Manager,
Developer Tools NVIDIA
NVIDIA

 

Thank you for this brilliant piece of engineering

Ala Shiban,
Haifa University,
Cancer Research Group
Haifa