mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	Add the X10 language (http://x10-lang.org/).
This commit is contained in:
		
							
								
								
									
										72
									
								
								samples/X10/ArraySum.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								samples/X10/ArraySum.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| import x10.io.Console; | ||||
|  | ||||
| /** | ||||
|  * A simple illustration of loop parallelization within a single place. | ||||
|  */ | ||||
| public class ArraySum { | ||||
|  | ||||
|     var sum:Long; | ||||
|     val data:Rail[Long]; | ||||
|  | ||||
|     public def this(n:Long) { | ||||
| 	// Create a Rail with n elements (0..(n-1)), all initialized to 1. | ||||
|         data = new Rail[Long](n, 1); | ||||
|         sum = 0; | ||||
|     } | ||||
|  | ||||
|     def sum(a:Rail[Long], start:Long, last:Long) { | ||||
|         var mySum: Long = 0; | ||||
|         for (i in start..(last-1)) {  | ||||
|         	mySum += a(i); | ||||
|         } | ||||
|         return mySum; | ||||
|     } | ||||
|  | ||||
|     def sum(numThreads:Long) { | ||||
|         val mySize = data.size/numThreads; | ||||
|         finish for (p in 0..(numThreads-1)) async { | ||||
|             val mySum = sum(data, p*mySize, (p+1)*mySize); | ||||
|             // Multiple activities will simultaneously update | ||||
|             // this location -- so use an atomic operation. | ||||
|             atomic sum += mySum; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     public static def main(args:Rail[String]) { | ||||
|         var size:Long = 5*1000*1000; | ||||
|         if (args.size >=1) | ||||
|             size = Long.parse(args(0)); | ||||
|  | ||||
|         Console.OUT.println("Initializing."); | ||||
|         val a = new ArraySum(size); | ||||
|         val P = [1,2,4]; | ||||
|  | ||||
|         //warmup loop | ||||
|         Console.OUT.println("Warming up."); | ||||
|         for (numThreads in P) | ||||
|             a.sum(numThreads); | ||||
|          | ||||
|         for (numThreads in P) { | ||||
|             Console.OUT.println("Starting with " + numThreads + " threads."); | ||||
|             a.sum=0; | ||||
|             var time: long = - System.nanoTime(); | ||||
|             a.sum(numThreads); | ||||
|             time += System.nanoTime(); | ||||
|             Console.OUT.println("For p=" + numThreads | ||||
|                     + " result: " + a.sum  | ||||
|                     + ((size==a.sum)? " ok" : "  bad")  | ||||
|                     + " (time=" + (time/(1000*1000)) + " ms)"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										50
									
								
								samples/X10/Cancellation.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								samples/X10/Cancellation.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| import x10.xrx.Runtime; | ||||
|  | ||||
| /** | ||||
|  * Demonstrate how to instantiate the X10 runtime as an executor service | ||||
|  * submit jobs to the runtime, wait jobs to complete and cancel all jobs | ||||
|  *  | ||||
|  * Compile with: x10c -O -EXECUTOR_MODE=true Cancellation.x10 | ||||
|  * Run with:     X10_CANCELLABLE=true X10_NPLACES=4 x10 -DX10RT_IMPL=JavaSockets Cancellation | ||||
|  */ | ||||
| class Cancellation { | ||||
|     static def job(id:Long, iterations:Long) = ()=>{ | ||||
|         at (Place.places().next(here)) async { | ||||
|             for (i in 1..iterations) { | ||||
|                 finish for (p in Place.places()) {  | ||||
|                     at (p) async Console.OUT.println(here+" says hello (job " + id + ", iteration " + i + ")"); | ||||
|                 } | ||||
|                 Console.ERR.println(); | ||||
|                 System.sleep(200); | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     public static def main(args:Rail[String]):void { | ||||
|         val w1 = Runtime.submit(job(1, 5)); | ||||
|         w1.await(); Console.ERR.println("Job 1 completed\n"); | ||||
|         val w2 = Runtime.submit(job(2, 1000)); | ||||
|         System.threadSleep(1000); | ||||
|         val c1 = Runtime.cancelAll(); | ||||
|         try { w2.await(); } catch (e:Exception) { Console.ERR.println("Job 2 aborted with exception " + e +"\n"); } | ||||
|         c1.await(); // waiting for cancellation to be processed | ||||
|         System.threadSleep(1000); | ||||
|         Runtime.submit(job(3, 1000)); | ||||
|         Runtime.submit(job(4, 1000)); | ||||
|         System.threadSleep(1000); | ||||
|         val c2 = Runtime.cancelAll(); | ||||
|         c2.await(); | ||||
|         Console.ERR.println("Goodbye\n"); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										52
									
								
								samples/X10/Fibonacci.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								samples/X10/Fibonacci.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| import x10.io.Console; | ||||
|  | ||||
| /** | ||||
|  * This is a small program to illustrate the use of  | ||||
|  * <code>async</code> and <code>finish</code> in a  | ||||
|  * prototypical recursive divide-and-conquer algorithm.   | ||||
|  * It is obviously not intended to show a efficient way to | ||||
|  * compute Fibonacci numbers in X10.<p> | ||||
|  * | ||||
|  * The heart of the example is the <code>run</code> method, | ||||
|  * which directly embodies the recursive definition of  | ||||
|  * <pre> | ||||
|  *   fib(n) = fib(n-1)+fib(n-2); | ||||
|  * </pre> | ||||
|  * by using an <code>async</code> to compute <code>fib(n-1)</code> while | ||||
|  * the current activity computes <code>fib(n-2)</code>.  A <code>finish</code> | ||||
|  * is used to ensure that both computations are complete before  | ||||
|  * their results are added together to compute <code>fib(n)</code> | ||||
|  */ | ||||
| public class Fibonacci { | ||||
|  | ||||
|   public static def fib(n:long) { | ||||
|     if (n<=2) return 1; | ||||
|      | ||||
|     val f1:long; | ||||
|     val f2:long; | ||||
|     finish { | ||||
|       async { f1 = fib(n-1); } | ||||
|       f2 = fib(n-2); | ||||
|     } | ||||
|     return f1 + f2; | ||||
|   } | ||||
|  | ||||
|   public static def main(args:Rail[String]) { | ||||
|     val n = (args.size > 0) ? Long.parse(args(0)) : 10; | ||||
|     Console.OUT.println("Computing fib("+n+")"); | ||||
|     val f = fib(n); | ||||
|     Console.OUT.println("fib("+n+") = "+f); | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										86
									
								
								samples/X10/HeatTransfer_v0.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								samples/X10/HeatTransfer_v0.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| import x10.array.*; | ||||
| import x10.compiler.Foreach; | ||||
| import x10.compiler.Inline; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * This is a sample program illustrating how to use | ||||
|  * X10's array classes.  It also illustrates the use | ||||
|  * of foreach to acheive intra-place parallelism. | ||||
|  * | ||||
|  * The program solves a set of 2D partial differential | ||||
|  * equations by iteratively applying a 5-point stencil | ||||
|  * operation until convergence is reached. | ||||
|  */ | ||||
| public class HeatTransfer_v0 { | ||||
|     static val EPSILON = 1.0e-5; | ||||
|  | ||||
|     val N:Long; | ||||
|     val A:Array_2[Double]{self!=null}; | ||||
|     val Tmp:Array_2[Double]{self!=null}; | ||||
|  | ||||
|     public def this(size:Long) { | ||||
|         N = size; | ||||
|         A = new Array_2[Double](N+2, N+2);  // zero-initialized N+2 * N+2 array of doubles | ||||
|         for (j in 1..N) A(0, j) = 1;     // set one border row to 1  | ||||
|         Tmp = new Array_2[Double](A); | ||||
|     } | ||||
|  | ||||
|     final @Inline def stencil(x:Long, y:Long):Double { | ||||
|         return (A(x-1,y) + A(x+1,y) + A(x,y-1) + A(x,y+1)) / 4; | ||||
|     } | ||||
|  | ||||
|     def run() { | ||||
|         val is = new DenseIterationSpace_2(1,1,N,N); | ||||
|         var delta:Double; | ||||
|         do { | ||||
|             // Compute new values, storing in tmp | ||||
|             delta = Foreach.blockReduce(is, | ||||
|                 (i:Long, j:Long)=>{ | ||||
|                     Tmp(i,j) = stencil(i,j); | ||||
|                     // Reduce max element-wise delta (A now holds previous values) | ||||
|                     return Math.abs(Tmp(i,j) - A(i,j)); | ||||
|                 }, | ||||
|                 (a:Double, b:Double)=>Math.max(a,b), 0.0 | ||||
|             ); | ||||
|  | ||||
|             // swap backing data of A and Tmp | ||||
|             Array.swap(A, Tmp); | ||||
|         } while (delta > EPSILON); | ||||
|     } | ||||
|  | ||||
|     def prettyPrintResult() { | ||||
|        for (i in 1..N) { | ||||
|            for (j in 1..N) { | ||||
|                 Console.OUT.printf("%1.4f ",A(i,j)); | ||||
|             } | ||||
|             Console.OUT.println(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static def main(args:Rail[String]) { | ||||
|         val n = args.size > 0 ? Long.parse(args(0)) : 8; | ||||
|         Console.OUT.println("HeatTransfer example with N="+n+" and epsilon="+EPSILON); | ||||
|         Console.OUT.println("Initializing data structures"); | ||||
|         val ht = new HeatTransfer_v0(n); | ||||
|         Console.OUT.println("Beginning computation..."); | ||||
|         val start = System.nanoTime(); | ||||
|         ht.run(); | ||||
|         val stop = System.nanoTime(); | ||||
|         Console.OUT.printf("...completed in %1.3f seconds.\n", ((stop-start) as double)/1e9); | ||||
|         if (n <= 10) { | ||||
|             ht.prettyPrintResult(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										114
									
								
								samples/X10/HeatTransfer_v1.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								samples/X10/HeatTransfer_v1.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| import x10.array.*; | ||||
| import x10.compiler.Foreach; | ||||
| import x10.util.Team; | ||||
|  | ||||
| /** | ||||
|  * This is a sample program illustrating how to use | ||||
|  * X10's distributed array classes.  It also illustrates the use | ||||
|  * of foreach to achieve intra-place parallelism and the mixture | ||||
|  * of APGAS finish/async/at with Team collective operations. | ||||
|  * | ||||
|  * This version of the program uses a vanilla DistArray without | ||||
|  * ghost regions.  As a result, the stencil function does | ||||
|  * inefficient fine-grained neighbor communication to get individual values. | ||||
|  * Compare this to HeatTransfer_v2 which utilizes ghost regions and | ||||
|  * bulk ghost-region exchange functions. | ||||
|  *  | ||||
|  * The program solves a set of 2D partial differential | ||||
|  * equations by iteratively applying a 5-point stencil | ||||
|  * operation until convergence is reached. | ||||
|  */ | ||||
| public class HeatTransfer_v1 { | ||||
|     static val EPSILON = 1.0e-5; | ||||
|  | ||||
|     val N:Long; | ||||
|     val A:DistArray_BlockBlock_2[Double]{self!=null}; | ||||
|     val Tmp:DistArray_BlockBlock_2[Double]{self!=null}; | ||||
|  | ||||
|     public def this(size:Long) { | ||||
|         N = size; | ||||
|         val init = (i:Long, j:Long)=>i==0 ? 1.0 : 0.0; | ||||
|         A = new DistArray_BlockBlock_2[Double](N+2, N+2, init); | ||||
|         Tmp = new DistArray_BlockBlock_2[Double](N+2, N+2, init); | ||||
|     } | ||||
|  | ||||
|     final def stencil(x:Long, y:Long):Double { | ||||
|         val cls = (dx:Long, dy:Long)=>{ | ||||
|             val p = A.place(x+dx, y+dy); | ||||
|             p == here ? A(x+dx,y+dy) : at (p) A(x+dx,y+dy) | ||||
|         }; | ||||
|         val tmp = cls(-1,0) + cls(1,0) + cls(0,-1) + cls(0,1); | ||||
|         return tmp / 4;  | ||||
|     } | ||||
|  | ||||
|     def run() { | ||||
|         val myTeam = new Team(A.placeGroup()); | ||||
|         finish for (p in A.placeGroup()) at (p) async { | ||||
|             // Compute the subset of the local indices on which | ||||
|             // we want to apply the stencil (the interior points of the N+2 x N+2 grid) | ||||
|             val li = A.localIndices(); | ||||
|             val interior = new DenseIterationSpace_2(li.min(0) == 0 ? 1 : li.min(0), | ||||
|                                                      li.min(1) == 0 ? 1 : li.min(1), | ||||
|                                                      li.max(0) == N+1 ? N : li.max(0), | ||||
|                                                      li.max(1) == N+1 ? N : li.max(1)); | ||||
|             var delta:Double; | ||||
|             do { | ||||
|                 // Compute new values, storing in tmp | ||||
|                 val myDelta = Foreach.blockReduce(interior, | ||||
|                     (i:Long, j:Long)=>{ | ||||
|                         Tmp(i,j) = stencil(i,j); | ||||
|                         // Reduce max element-wise delta (A now holds previous values) | ||||
|                         return Math.abs(Tmp(i,j) - A(i,j)); | ||||
|                     }, | ||||
|                     (a:Double, b:Double)=>Math.max(a,b), 0.0 | ||||
|                 ); | ||||
|  | ||||
|                 myTeam.barrier(); | ||||
|  | ||||
|                 // Unlike Array, DistArray doesn't provide an optimized swap. | ||||
|                 // So, until it does, we have to copy the data elements. | ||||
|                 Foreach.block(interior, (i:Long, j:Long)=>{ | ||||
|                     A(i,j) = Tmp(i,j); | ||||
|                 }); | ||||
|  | ||||
|                 delta = myTeam.allreduce(myDelta, Team.MAX); | ||||
|             } while (delta > EPSILON); | ||||
|         } | ||||
|     } | ||||
|   | ||||
|    def prettyPrintResult() { | ||||
|        for (i in 1..N) { | ||||
|            for (j in 1..N) { | ||||
|                 val x = at (A.place(i,j)) A(i,j); | ||||
|                 Console.OUT.printf("%1.4f ", x); | ||||
|             } | ||||
|             Console.OUT.println(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static def main(args:Rail[String]) { | ||||
|         val n = args.size > 0 ? Long.parse(args(0)) : 8; | ||||
|         Console.OUT.println("HeatTransfer example with N="+n+" and epsilon="+EPSILON); | ||||
|         Console.OUT.println("Initializing data structures"); | ||||
|         val ht = new HeatTransfer_v1(n); | ||||
|         Console.OUT.println("Beginning computation..."); | ||||
|         val start = System.nanoTime(); | ||||
|         ht.run(); | ||||
|         val stop = System.nanoTime(); | ||||
|         Console.OUT.printf("...completed in %1.3f seconds.\n", ((stop-start) as double)/1e9); | ||||
|         if (n <= 10) { | ||||
|             ht.prettyPrintResult(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										44
									
								
								samples/X10/HelloWholeWorld.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								samples/X10/HelloWholeWorld.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| import x10.io.Console; | ||||
|  | ||||
| /** | ||||
|  * The classic hello world program, with a twist - prints a message | ||||
|  * from the command line at every Place.  | ||||
|  * The messages from each Place may appear in any order, but the | ||||
|  * finish ensures that the last message printed will be "Goodbye" | ||||
|  * <pre> | ||||
|  * Typical output: | ||||
|  * [dgrove@linchen samples]$ ./HelloWholeWorld 'best wishes' | ||||
|  * Place(1) says hello and best wishes | ||||
|  * Place(2) says hello and best wishes | ||||
|  * Place(3) says hello and best wishes | ||||
|  * Place(0) says hello and best wishes | ||||
|  * Goodbye  | ||||
|  * [dgrove@linchen samples]$ | ||||
|  * </pre> | ||||
|  */ | ||||
| class HelloWholeWorld { | ||||
|   public static def main(args:Rail[String]):void { | ||||
|      if (args.size < 1) { | ||||
|          Console.OUT.println("Usage: HelloWholeWorld message"); | ||||
|          return; | ||||
|      } | ||||
|      | ||||
|      finish for (p in Place.places()) { | ||||
|      	at (p) async Console.OUT.println(here+" says hello and "+args(0)); | ||||
|      } | ||||
|      Console.OUT.println("Goodbye"); | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										23
									
								
								samples/X10/HelloWorld.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								samples/X10/HelloWorld.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| import x10.io.Console; | ||||
|  | ||||
| /** | ||||
|  * The classic hello world program, shows how to output to the console. | ||||
|  */ | ||||
| class HelloWorld { | ||||
|   public static def main(Rail[String]) { | ||||
|       Console.OUT.println("Hello World!" ); | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										45
									
								
								samples/X10/Histogram.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								samples/X10/Histogram.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| public class Histogram { | ||||
|     public static def compute(data:Rail[Int], numBins:Int) { | ||||
|         val bins = new Rail[Int](numBins); | ||||
|         finish for (i in data.range) async { | ||||
|            val b = data(i) % numBins; | ||||
|            atomic bins(b)++; | ||||
|         } | ||||
|         return bins; | ||||
|     } | ||||
|  | ||||
|     public static def run(N:Int, S:Int):Boolean { | ||||
|         val a = new Rail[Int](N, (i:long)=> i as int); | ||||
|         val b = compute(a, S); | ||||
|         val v = b(0); | ||||
|         var ok:Boolean = true; | ||||
|         for (x in b.range) ok &= (b(x)==v); | ||||
|         return ok; | ||||
|     } | ||||
|  | ||||
|     public static def main(args:Rail[String]) { | ||||
|         if (args.size != 2L) { | ||||
|             Console.OUT.println("Usage: Histogram SizeOfArray NumberOfBins"); | ||||
|             return; | ||||
|         } | ||||
|         val N = Int.parse(args(0)); | ||||
|         val S = Int.parse(args(1)); | ||||
|         val ok = run(N,S); | ||||
|         if (ok) { | ||||
|             Console.OUT.println("Test ok."); | ||||
|         } else { | ||||
|             Console.OUT.println("Test failed."); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										55
									
								
								samples/X10/Integrate.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								samples/X10/Integrate.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * This is a slightly more realistic example of the | ||||
|  * basic computational pattern of using async/finish | ||||
|  * to express recursive divide-and-conquer algorithms. | ||||
|  * The program does integration via Guassian Quadrature. | ||||
|  * <p> | ||||
|  * It also can serve as an example of using a closure. | ||||
|  */ | ||||
| public class Integrate {  | ||||
|   static val epsilon = 1.0e-9; | ||||
|  | ||||
|   val fun:(double)=>double; | ||||
|  | ||||
|   public def this(f:(double)=>double) { fun = f; } | ||||
|  | ||||
|   public def computeArea(left:double, right:double) { | ||||
|     return recEval(left, fun(left), right, fun(right), 0); | ||||
|   } | ||||
|  | ||||
|   private def recEval(l:double, fl:double, r:double, fr:double, a:double) { | ||||
|     val h = (r - l) / 2; | ||||
|     val hh = h / 2; | ||||
|     val c = l + h; | ||||
|     val fc = fun(c); | ||||
|     val al = (fl + fc) * hh;    | ||||
|     val ar = (fr + fc) * hh; | ||||
|     val alr = al + ar; | ||||
|     if (Math.abs(alr - a) < epsilon) return alr; | ||||
|     val expr1:double; | ||||
|     val expr2:double; | ||||
|     finish { | ||||
|       async { expr1 = recEval(c, fc, r, fr, ar); }; | ||||
|       expr2 = recEval(l, fl, c, fc, al); | ||||
|     } | ||||
|     return expr1 + expr2; | ||||
|   } | ||||
|   | ||||
|   public static def main(args:Rail[String]) { | ||||
|     val obj = new Integrate((x:double)=>(x*x + 1.0) * x); | ||||
|     val xMax = args.size > 0 ? Long.parse(args(0)) : 10; | ||||
|     val area = obj.computeArea(0, xMax); | ||||
|     Console.OUT.println("The area of (x*x +1) * x from 0 to "+xMax+" is "+area); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										151
									
								
								samples/X10/KMeans.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								samples/X10/KMeans.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,151 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| import x10.io.Console; | ||||
| import x10.util.Random; | ||||
|  | ||||
| /** | ||||
|  * A KMeans object o can compute K means of a given set of  | ||||
|  * points of dimension o.myDim. | ||||
|  * <p>  | ||||
|  * This class implements a sequential program, that is readily parallelizable. | ||||
|  * | ||||
|  * For a scalable, high-performance version of this benchmark see | ||||
|  * KMeans.x10 in the X10 Benchmarks (separate download from x10-lang.org) | ||||
|  */ | ||||
| public class KMeans(myDim:Long) { | ||||
|  | ||||
|     static val DIM=2; | ||||
|     static val K=4; | ||||
|     static val POINTS=2000; | ||||
|     static val ITERATIONS=50; | ||||
|     static val EPS=0.01F; | ||||
|      | ||||
|     static type ValVector(k:Long) = Rail[Float]{self.size==k}; | ||||
|     static type ValVector = ValVector(DIM); | ||||
|      | ||||
|     static type Vector(k:Long) = Rail[Float]{self.size==k}; | ||||
|     static type Vector = Vector(DIM); | ||||
|      | ||||
|     static type SumVector(d:Long) = V{self.dim==d}; | ||||
|     static type SumVector = SumVector(DIM); | ||||
|  | ||||
|     /** | ||||
|      * V represents the sum of 'count' number of vectors of dimension 'dim'. | ||||
|      */ | ||||
|     static class V(dim:Long) implements (Long)=>Float { | ||||
|         var vec: Vector(dim); | ||||
|         var count:Int; | ||||
|         def this(dim:Long, init:(Long)=>Float): SumVector(dim) { | ||||
|            property(dim); | ||||
|            vec = new Rail[Float](this.dim, init); | ||||
|            count = 0n; | ||||
|         } | ||||
|         public operator this(i:Long) = vec(i); | ||||
|         def makeZero() { | ||||
|             for (i in 0..(dim-1)) | ||||
|                 vec(i) =0.0F; | ||||
|             count=0n; | ||||
|         } | ||||
|         def addIn(a:ValVector(dim)) { | ||||
|             for (i in 0..(dim-1)) | ||||
|                 vec(i) += a(i); | ||||
|             count++; | ||||
|         } | ||||
|         def div(f:Int) { | ||||
|             for (i in 0..(dim-1)) | ||||
|                 vec(i) /= f; | ||||
|         } | ||||
|         def dist(a:ValVector(dim)):Float { | ||||
|             var dist:Float=0.0F; | ||||
|             for (i in 0..(dim-1)) { | ||||
|                 val tmp = vec(i)-a(i); | ||||
|                 dist += tmp*tmp; | ||||
|             } | ||||
|             return dist; | ||||
|         } | ||||
|         def dist(a:SumVector(dim)):Float { | ||||
|             var dist:Float=0.0F; | ||||
|             for (i in 0..(dim-1)) { | ||||
|                 val tmp = vec(i)-a(i); | ||||
|                 dist += tmp*tmp; | ||||
|             } | ||||
|             return dist; | ||||
|         } | ||||
|         def print() { | ||||
|             Console.OUT.println(); | ||||
|             for (i in 0..(dim-1)) { | ||||
|                 Console.OUT.print((i>0? " " : "") + vec(i)); | ||||
|             } | ||||
|         } | ||||
|         def normalize() { div(count);} | ||||
|         def count() = count; | ||||
|     } | ||||
|      | ||||
|      | ||||
|     def this(myDim:Long):KMeans{self.myDim==myDim} { | ||||
|         property(myDim); | ||||
|     } | ||||
|     static type KMeansData(myK:Long, myDim:Long)= Rail[SumVector(myDim)]{self.size==myK}; | ||||
|  | ||||
|     /** | ||||
|      * Compute myK means for the given set of points of dimension myDim. | ||||
|      */ | ||||
|     def computeMeans(myK:Long, points:Rail[ValVector(myDim)]):KMeansData(myK, myDim) { | ||||
|         var redCluster : KMeansData(myK, myDim) = | ||||
|             new Rail[SumVector(myDim)](myK, (i:long)=> new V(myDim, (j:long)=>points(i)(j))); | ||||
|         var blackCluster: KMeansData(myK, myDim) = | ||||
|             new Rail[SumVector(myDim)](myK, (i:long)=> new V(myDim, (j:long)=>0.0F)); | ||||
|         for (i in 1..ITERATIONS) { | ||||
|             val tmp = redCluster; | ||||
|             redCluster = blackCluster; | ||||
|             blackCluster=tmp; | ||||
|             for (p in 0..(POINTS-1)) {  | ||||
|                 var closest:Long = -1; | ||||
|                 var closestDist:Float = Float.MAX_VALUE; | ||||
|                 val point = points(p); | ||||
|                 for (k in 0..(myK-1)) { // compute closest mean in cluster. | ||||
|                     val dist = blackCluster(k).dist(point); | ||||
|                     if (dist < closestDist) { | ||||
|                         closestDist = dist; | ||||
|                         closest = k; | ||||
|                     } | ||||
|                 } | ||||
|                 redCluster(closest).addIn(point); | ||||
|             } | ||||
|             for (k in 0..(myK-1)) | ||||
|                 redCluster(k).normalize();  | ||||
|              | ||||
|             var b:Boolean = true; | ||||
|                 for (k in 0..(myK-1)) { | ||||
|                     if (redCluster(k).dist(blackCluster(k)) > EPS) { | ||||
|                         b=false; | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|             if (b)  | ||||
|                 break; | ||||
|             for (k in 0..(myK-1)) | ||||
|                 blackCluster(k).makeZero();  | ||||
|         } | ||||
|         return redCluster;   | ||||
|     } | ||||
|    | ||||
|     public static def main (Rail[String]) { | ||||
|         val rnd = new Random(0); | ||||
|         val points = new Rail[ValVector](POINTS,  | ||||
|                         (long)=>new Rail[Float](DIM, (long)=>rnd.nextFloat())); | ||||
|         val result = new KMeans(DIM).computeMeans(K, points); | ||||
|         for (k in 0..(K-1)) result(k).print(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // vim: shiftwidth=4:tabstop=4:expandtab | ||||
							
								
								
									
										147
									
								
								samples/X10/KMeansDist.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								samples/X10/KMeansDist.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| import x10.array.*; | ||||
| import x10.io.Console; | ||||
| import x10.util.Random; | ||||
|  | ||||
| /** | ||||
|  * A low performance formulation of distributed KMeans using fine-grained asyncs. | ||||
|  * | ||||
|  * For a highly optimized and scalable, version of this benchmark see | ||||
|  * KMeans.x10 in the X10 Benchmarks (separate download from x10-lang.org) | ||||
|  */ | ||||
| public class KMeansDist { | ||||
|  | ||||
|     static val DIM=2; | ||||
|     static val CLUSTERS=4; | ||||
|     static val POINTS=2000; | ||||
|     static val ITERATIONS=50; | ||||
|  | ||||
|     public static def main (Rail[String]) { | ||||
|         val world = Place.places(); | ||||
|         val local_curr_clusters =  | ||||
|             PlaceLocalHandle.make[Array_2[Float]](world, () => new Array_2[Float](CLUSTERS, DIM)); | ||||
|         val local_new_clusters =  | ||||
|             PlaceLocalHandle.make[Array_2[Float]](world, () =>  new Array_2[Float](CLUSTERS, DIM)); | ||||
|         val local_cluster_counts =  | ||||
|             PlaceLocalHandle.make[Rail[Int]](world, ()=> new Rail[Int](CLUSTERS)); | ||||
|  | ||||
|         val rnd = PlaceLocalHandle.make[Random](world, () => new Random(0)); | ||||
|         val points = new DistArray_Block_2[Float](POINTS, DIM, world, (Long,Long)=>rnd().nextFloat()); | ||||
|  | ||||
|         val central_clusters = new Array_2[Float](CLUSTERS, DIM, (i:Long, j:Long) => { | ||||
|             at (points.place(i,j)) points(i,j) | ||||
|         }); | ||||
|  | ||||
| 	val old_central_clusters = new Array_2[Float](CLUSTERS, DIM); | ||||
|  | ||||
|         val central_cluster_counts = new Rail[Int](CLUSTERS); | ||||
|  | ||||
|         for (iter in 1..ITERATIONS) { | ||||
|  | ||||
|             Console.OUT.println("Iteration: "+iter); | ||||
|  | ||||
|             finish { | ||||
|                 // reset state | ||||
|                 for (d in world) at (d) async { | ||||
|                     for ([i,j] in central_clusters.indices()) { | ||||
|                         local_curr_clusters()(i, j) = central_clusters(i, j); | ||||
|                         local_new_clusters()(i, j) = 0f; | ||||
|                     } | ||||
|              | ||||
|                     local_cluster_counts().clear(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             finish { | ||||
|                 // compute new clusters and counters | ||||
|                 for (p in 0..(POINTS-1)) { | ||||
|                     at (points.place(p,0)) async { | ||||
|                         var closest:Long = -1; | ||||
|                         var closest_dist:Float = Float.MAX_VALUE; | ||||
|                         for (k in 0..(CLUSTERS-1)) {  | ||||
|                             var dist : Float = 0; | ||||
|                             for (d in 0..(DIM-1)) {  | ||||
|                                 val tmp = points(p,d) - local_curr_clusters()(k, d); | ||||
|                                 dist += tmp * tmp; | ||||
|                             } | ||||
|                             if (dist < closest_dist) { | ||||
|                                 closest_dist = dist; | ||||
|                                 closest = k; | ||||
|                             } | ||||
|                         } | ||||
| 			atomic { | ||||
|                             for (d in 0..(DIM-1)) {  | ||||
|                                 local_new_clusters()(closest,d) += points(p,d); | ||||
|                             } | ||||
|                             local_cluster_counts()(closest)++; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             for ([i,j] in old_central_clusters.indices()) { | ||||
|                 old_central_clusters(i, j) = central_clusters(i, j); | ||||
|                 central_clusters(i, j) = 0f; | ||||
|             } | ||||
|             | ||||
|             central_cluster_counts.clear(); | ||||
|  | ||||
|             finish { | ||||
|                 val central_clusters_gr = GlobalRef(central_clusters); | ||||
|                 val central_cluster_counts_gr = GlobalRef(central_cluster_counts); | ||||
|                 val there = here; | ||||
|                 for (d in world) at (d) async { | ||||
|                     // access PlaceLocalHandles 'here' and then data will be captured by at and transfered to 'there' for accumulation | ||||
|                     val tmp_new_clusters = local_new_clusters(); | ||||
|                     val tmp_cluster_counts = local_cluster_counts(); | ||||
|                     at (there) atomic { | ||||
|                         for ([i,j] in tmp_new_clusters.indices()) { | ||||
|                             central_clusters_gr()(i,j) += tmp_new_clusters(i,j); | ||||
|                         } | ||||
|                         for (j in 0..(CLUSTERS-1)) { | ||||
|                             central_cluster_counts_gr()(j) += tmp_cluster_counts(j); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             for (k in 0..(CLUSTERS-1)) {  | ||||
|                 for (d in 0..(DIM-1)) {  | ||||
|                     central_clusters(k, d) /= central_cluster_counts(k); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // TEST FOR CONVERGENCE | ||||
|             var b:Boolean = true; | ||||
|             for ([i,j] in old_central_clusters.indices()) {  | ||||
|                 if (Math.abs(old_central_clusters(i, j)-central_clusters(i, j))>0.0001) { | ||||
|                     b = false; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             if (b) break; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         for (d in 0..(DIM-1)) {  | ||||
|             for (k in 0..(CLUSTERS-1)) {  | ||||
|                 if (k>0) | ||||
|                     Console.OUT.print(" "); | ||||
|                 Console.OUT.print(central_clusters(k,d)); | ||||
|             } | ||||
|             Console.OUT.println(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // vim: shiftwidth=4:tabstop=4:expandtab | ||||
							
								
								
									
										144
									
								
								samples/X10/KMeansDistPlh.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								samples/X10/KMeansDistPlh.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2015. | ||||
|  */ | ||||
|  | ||||
| import x10.array.Array; | ||||
| import x10.array.Array_2; | ||||
| import x10.compiler.Foreach; | ||||
| import x10.util.Random; | ||||
|  | ||||
| /** | ||||
|  * A better formulation of distributed KMeans using coarse-grained asyncs to | ||||
|  * implement an allreduce pattern for cluster centers and counts. | ||||
|  * | ||||
|  * For a highly optimized and scalable, version of this benchmark see | ||||
|  * KMeans.x10 in the X10 Benchmarks (separate download from x10-lang.org) | ||||
|  */ | ||||
| public class KMeansDistPlh { | ||||
|  | ||||
|     static val DIM=2; | ||||
|     static val CLUSTERS=4; | ||||
|  | ||||
|     static class ClusterState { | ||||
|         val clusters = new Array_2[Float](CLUSTERS, DIM); | ||||
|         val clusterCounts = new Rail[Int](CLUSTERS); | ||||
|     } | ||||
|  | ||||
|     public static def main(args:Rail[String]) { | ||||
|         val numPoints = args.size > 0 ? Long.parse(args(0)) : 2000; | ||||
|         val iterations = args.size > 1 ? Long.parse(args(1)) : 50; | ||||
|         val world = Place.places(); | ||||
|  | ||||
|         val clusterStatePlh = PlaceLocalHandle.make[ClusterState](world, () => new ClusterState()); | ||||
|         val currentClustersPlh = PlaceLocalHandle.make[Array_2[Float]](world, () => new Array_2[Float](CLUSTERS, DIM)); | ||||
|         val pointsPlh = PlaceLocalHandle.make[Array_2[Float]](world, () => { | ||||
|             val rand = new Random(here.id); | ||||
|             return new Array_2[Float](numPoints/world.size(), DIM, (Long,Long)=>rand.nextFloat()); | ||||
|         }); | ||||
|  | ||||
|         val centralCurrentClusters = new Array_2[Float](CLUSTERS, DIM); | ||||
|         val centralNewClusters = new Array_2[Float](CLUSTERS, DIM); | ||||
|         val centralClusterCounts = new Rail[Int](CLUSTERS); | ||||
|  | ||||
|         // arbitrarily initialize central clusters to first few points | ||||
|         for ([i,j] in centralCurrentClusters.indices()) { | ||||
|             centralCurrentClusters(i,j) = pointsPlh()(i,j); | ||||
|         } | ||||
|  | ||||
|         for (iter in 1..iterations) { | ||||
|             Console.OUT.println("Iteration: "+iter); | ||||
|  | ||||
|             finish { | ||||
|                 for (place in world) async { | ||||
|                     val placeClusters = at(place) { | ||||
|                         val currentClusters = currentClustersPlh(); | ||||
|                         Array.copy(centralCurrentClusters, currentClusters); | ||||
|  | ||||
|                         val clusterState = clusterStatePlh(); | ||||
|                         val newClusters = clusterState.clusters; | ||||
|                         newClusters.clear(); | ||||
|                         val clusterCounts = clusterState.clusterCounts; | ||||
|                         clusterCounts.clear(); | ||||
|  | ||||
|                         // compute new clusters and counters | ||||
|                         val points = pointsPlh(); | ||||
|  | ||||
|                         for (p in 0..(points.numElems_1-1)) { | ||||
|                             var closest:Long = -1; | ||||
|                             var closestDist:Float = Float.MAX_VALUE; | ||||
|                             for (k in 0..(CLUSTERS-1)) {  | ||||
|                                 var dist : Float = 0; | ||||
|                                 for (d in 0..(DIM-1)) {  | ||||
|                                     val tmp = points(p,d) - currentClusters(k, d); | ||||
|                                     dist += tmp * tmp; | ||||
|                                 } | ||||
|                                 if (dist < closestDist) { | ||||
|                                     closestDist = dist; | ||||
|                                     closest = k; | ||||
|                                 } | ||||
|                             } | ||||
|  | ||||
|                             atomic { | ||||
|                                 for (d in 0..(DIM-1)) {  | ||||
|                                     newClusters(closest,d) += points(p,d); | ||||
|                                 } | ||||
|                                 clusterCounts(closest)++; | ||||
|                             } | ||||
|                         } | ||||
|                         clusterState | ||||
|                     }; | ||||
|  | ||||
|                     // combine place clusters to central | ||||
|                     atomic { | ||||
|                         for ([i,j] in centralNewClusters.indices()) { | ||||
|                             centralNewClusters(i,j) += placeClusters.clusters(i,j); | ||||
|                         } | ||||
|                         for (j in 0..(CLUSTERS-1)) { | ||||
|                             centralClusterCounts(j) += placeClusters.clusterCounts(j); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             for (k in 0..(CLUSTERS-1)) {  | ||||
|                 for (d in 0..(DIM-1)) {  | ||||
|                     centralNewClusters(k, d) /= centralClusterCounts(k); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // TEST FOR CONVERGENCE | ||||
|             var b:Boolean = true; | ||||
|             for ([i,j] in centralCurrentClusters.indices()) {  | ||||
|                 if (Math.abs(centralCurrentClusters(i, j)-centralNewClusters(i, j)) > 0.0001) { | ||||
|                     b = false; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             Array.copy(centralNewClusters, centralCurrentClusters); | ||||
|  | ||||
|             if (b) break; | ||||
|  | ||||
|             centralNewClusters.clear(); | ||||
|             centralClusterCounts.clear(); | ||||
|         } | ||||
|  | ||||
|         for (d in 0..(DIM-1)) {  | ||||
|             for (k in 0..(CLUSTERS-1)) {  | ||||
|                 if (k > 0) | ||||
|                     Console.OUT.print(" "); | ||||
|                 Console.OUT.print(centralCurrentClusters(k,d)); | ||||
|             } | ||||
|             Console.OUT.println(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // vim: shiftwidth=4:tabstop=4:expandtab | ||||
							
								
								
									
										192
									
								
								samples/X10/KMeansSPMD.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								samples/X10/KMeansSPMD.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,192 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| import x10.io.Console; | ||||
| import x10.io.File; | ||||
| import x10.io.Marshal; | ||||
| import x10.io.IOException; | ||||
| import x10.util.OptionsParser; | ||||
| import x10.util.Option; | ||||
| import x10.util.Team; | ||||
|  | ||||
| /** | ||||
|  * An SPMD formulation of KMeans. | ||||
|  * | ||||
|  * For a highly optimized and scalable version of this benchmark see | ||||
|  * KMeans.x10 in the X10 Benchmarks (separate download from x10-lang.org) | ||||
|  */ | ||||
| public class KMeansSPMD { | ||||
|  | ||||
|     public static def printClusters (clusters:Rail[Float], dims:long) { | ||||
|         for (d in 0..(dims-1)) {  | ||||
|             for (k in 0..(clusters.size/dims-1)) {  | ||||
|                 if (k>0) | ||||
|                     Console.OUT.print(" "); | ||||
|                 Console.OUT.print(clusters(k*dims+d).toString()); | ||||
|             } | ||||
|             Console.OUT.println(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static def main (args:Rail[String]) {here == Place.FIRST_PLACE } { | ||||
|  | ||||
|         val opts = new OptionsParser(args, [ | ||||
|             Option("q","quiet","just print time taken"), | ||||
|             Option("v","verbose","print out each iteration"), | ||||
|             Option("h","help","this information") | ||||
|         ], [ | ||||
|             Option("p","points","location of data file"), | ||||
|             Option("i","iterations","quit after this many iterations"), | ||||
|             Option("c","clusters","number of clusters to find"), | ||||
|             Option("d","dim","number of dimensions"), | ||||
|             Option("s","slices","factor by which to oversubscribe computational resources"), | ||||
|             Option("n","num","quantity of points") | ||||
|         ]); | ||||
|         if (opts.filteredArgs().size!=0L) { | ||||
|             Console.ERR.println("Unexpected arguments: "+opts.filteredArgs()); | ||||
|             Console.ERR.println("Use -h or --help."); | ||||
|             System.setExitCode(1n); | ||||
|             return; | ||||
|         } | ||||
|         if (opts("-h")) { | ||||
|             Console.OUT.println(opts.usage("")); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         val fname = opts("-p", "points.dat"); | ||||
|         val num_clusters=opts("-c",4); | ||||
|         val num_slices=opts("-s",1); | ||||
|         val num_global_points=opts("-n", 2000); | ||||
|         val iterations=opts("-i",50); | ||||
|         val dim=opts("-d", 4); | ||||
|         val verbose = opts("-v"); | ||||
|         val quiet = opts("-q"); | ||||
|  | ||||
|         if (!quiet) | ||||
|             Console.OUT.println("points: "+num_global_points+" clusters: "+num_clusters+" dim: "+dim); | ||||
|  | ||||
|         // file is dimension-major | ||||
|         val file = new File(fname); | ||||
|         val fr = file.openRead(); | ||||
|         val init_points = (long) => Float.fromIntBits(Marshal.INT.read(fr).reverseBytes()); | ||||
|         val num_file_points = (file.size() / dim / 4) as Int; | ||||
|         val file_points = new Rail[Float](num_file_points*dim, init_points); | ||||
|  | ||||
|         val team = Team.WORLD; | ||||
|  | ||||
|         val num_slice_points = num_global_points / num_slices / Place.numPlaces(); | ||||
|  | ||||
|         finish { | ||||
|             for (h in Place.places()) at(h) async { | ||||
|                 var compute_time:Long = 0; | ||||
|                 var comm_time:Long = 0; | ||||
|                 var barrier_time:Long = 0; | ||||
|  | ||||
|                 val host_clusters  = new Rail[Float](num_clusters*dim, (i:long)=>file_points(i)); | ||||
|                 val host_cluster_counts = new Rail[Int](num_clusters); | ||||
|  | ||||
|                 for (slice in 0..(num_slices-1)) { | ||||
|                     // carve out local portion of points (point-major) | ||||
|                     val offset = (slice*Place.numPlaces() + here.id) * num_slice_points; | ||||
|                     if (verbose) | ||||
|                         Console.OUT.println(h.toString()+" gets "+offset+" len "+num_slice_points); | ||||
|                     val init = (i:long) => { | ||||
|                         val p=i%num_slice_points; | ||||
|                         val d=i/num_slice_points; | ||||
|                         return file_points(offset+p+d*num_file_points); | ||||
|                     }; | ||||
|  | ||||
|                     // these are pretty big so allocate up front | ||||
|                     val host_points = new Rail[Float](num_slice_points*dim, init); | ||||
|                     val host_nearest = new Rail[Float](num_slice_points); | ||||
|  | ||||
|                     val start_time = System.currentTimeMillis(); | ||||
|  | ||||
|                     barrier_time -= System.nanoTime(); | ||||
|                     team.barrier(); | ||||
|                     barrier_time += System.nanoTime(); | ||||
|  | ||||
|                     main_loop: for (iter in 0..(iterations-1)) { | ||||
|  | ||||
|                         //if (offset==0) Console.OUT.println("Iteration: "+iter); | ||||
|  | ||||
|                         val old_clusters = new Rail[Float](host_clusters.size); | ||||
|                         Rail.copy(host_clusters, 0L, old_clusters, 0L, host_clusters.size); | ||||
|  | ||||
|                         host_clusters.clear(); | ||||
|                         host_cluster_counts.clear(); | ||||
|  | ||||
|                         compute_time -= System.nanoTime(); | ||||
|                         for (p in 0..(num_slice_points-1)) { | ||||
|                             var closest:Long = -1; | ||||
|                             var closest_dist:Float = Float.MAX_VALUE; | ||||
|                             for (k in 0..(num_clusters-1)) {  | ||||
|                                 var dist : Float = 0; | ||||
|                                 for (d in 0..(dim-1)) {  | ||||
|                                     val tmp = host_points(p+d*num_slice_points) - old_clusters(k*dim+d); | ||||
|                                     dist += tmp * tmp; | ||||
|                                 } | ||||
|                                 if (dist < closest_dist) { | ||||
|                                     closest_dist = dist; | ||||
|                                     closest = k; | ||||
|                                 } | ||||
|                             } | ||||
|                             for (d in 0..(dim-1)) {  | ||||
|                                 host_clusters(closest*dim+d) += host_points(p+d*num_slice_points); | ||||
|                             } | ||||
|                             host_cluster_counts(closest)++; | ||||
|                         } | ||||
|                         compute_time += System.nanoTime(); | ||||
|  | ||||
|                         comm_time -= System.nanoTime(); | ||||
|                         team.allreduce(host_clusters, 0L, host_clusters, 0L, host_clusters.size, Team.ADD); | ||||
|                         team.allreduce(host_cluster_counts, 0L, host_cluster_counts, 0L, host_cluster_counts.size, Team.ADD); | ||||
|                         comm_time += System.nanoTime(); | ||||
|  | ||||
|                         for (k in 0..(num_clusters-1)) { | ||||
|                             for (d in 0..(dim-1)) host_clusters(k*dim+d) /= host_cluster_counts(k); | ||||
|                         } | ||||
|  | ||||
|                         if (offset==0 && verbose) { | ||||
|                             Console.OUT.println("Iteration: "+iter); | ||||
|                             printClusters(host_clusters,dim); | ||||
|                         } | ||||
|  | ||||
|                         // TEST FOR CONVERGENCE | ||||
|                         for (j in 0..(num_clusters*dim-1)) { | ||||
|                             if (true/*||Math.abs(clusters_old(j)-host_clusters(j))>0.0001*/) continue main_loop; | ||||
|                         } | ||||
|  | ||||
|                         break; | ||||
|  | ||||
|                     } // main_loop | ||||
|  | ||||
|                 } // slice | ||||
|  | ||||
|                 Console.OUT.printf("%d: computation %.3f s communication %.3f s (barrier %.3f s)\n",  | ||||
|                     here.id, compute_time/1E9, comm_time/1E9, barrier_time/1E9); | ||||
|  | ||||
|                 team.barrier(); | ||||
|  | ||||
|                 if (here.id == 0) { | ||||
|                     Console.OUT.println("\nFinal results:"); | ||||
|                     printClusters(host_clusters,dim); | ||||
|                 } | ||||
|  | ||||
|             } // async | ||||
|  | ||||
|         } // finish | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| // vim: shiftwidth=4:tabstop=4:expandtab | ||||
							
								
								
									
										42
									
								
								samples/X10/MontyPi.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								samples/X10/MontyPi.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| import x10.array.DistArray_Unique; | ||||
| import x10.io.Console; | ||||
| import x10.util.Random; | ||||
|  | ||||
| /** | ||||
|  * Calculation of an approximation to pi by using a Monte Carlo simulation | ||||
|  * (throwing darts into the unit square and determining the fraction that land | ||||
|  * in the unit circle). | ||||
|  */ | ||||
| public class MontyPi { | ||||
|     public static def main(args:Rail[String]) { | ||||
|         if (args.size != 1L) { | ||||
|             Console.OUT.println("Usage: MontyPi <number of points>"); | ||||
|             return; | ||||
|         } | ||||
|         val N = Long.parse(args(0)); | ||||
|         val initializer = () => { | ||||
|             val r = new Random(); | ||||
|             var result:Long = 0; | ||||
|             for(c in 1..N) { | ||||
|                 val x = r.nextDouble(); | ||||
|                 val y = r.nextDouble(); | ||||
|                 if (x*x +y*y <= 1.0) result++; | ||||
|             } | ||||
|             result | ||||
|         }; | ||||
|         val result = new DistArray_Unique[Long](Place.places(), initializer); | ||||
|         val pi = (4.0*result.reduce((x:Long,y:Long) => x+y, 0) as Double)/(N*Place.numPlaces()); | ||||
|         Console.OUT.println("The value of pi is " + pi); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										123
									
								
								samples/X10/NQueensDist.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								samples/X10/NQueensDist.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  *  (C) Copyright Australian National University 2011. | ||||
|  */ | ||||
|  | ||||
| import x10.array.DistArray_Unique; | ||||
|  | ||||
| /** | ||||
|  * A distributed version of NQueens. Runs over NUM_PLACES. | ||||
|  * Identical to NQueensPar, except that work is distributed  | ||||
|  * over multiple places rather than shared between threads. | ||||
|  */ | ||||
| public class NQueensDist { | ||||
|     public static val EXPECTED_SOLUTIONS = | ||||
|         [0, 1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680, 14200, 73712, 365596, 2279184, 14772512]; | ||||
|  | ||||
|     val N:Long; | ||||
|     val P:Long; | ||||
|     val results:DistArray_Unique[Long]; | ||||
|     val R:LongRange; | ||||
|  | ||||
|     def this(N:Long, P:Long) {  | ||||
|         this.N=N; | ||||
|         this.P=P; | ||||
|         this.results = new DistArray_Unique[Long](); | ||||
|         this.R = 0..(N-1); | ||||
|     } | ||||
|     def start() { | ||||
|         new Board().distSearch(); | ||||
|     } | ||||
|     def run():Long { | ||||
|        finish start(); | ||||
|        val result = results.reduce(((x:Long,y:Long) => x+y),0); | ||||
|        return result; | ||||
|     } | ||||
|  | ||||
|     class Board { | ||||
|         val q: Rail[Long]; | ||||
|         /** The number of low-rank positions that are fixed in this board for the purposes of search. */ | ||||
|         var fixed:Long; | ||||
|         def this() { | ||||
|             q = new Rail[Long](N); | ||||
|             fixed = 0; | ||||
|         } | ||||
|  | ||||
|         /**  | ||||
|          * @return true if it is safe to put a queen in file <code>j</code> | ||||
|          * on the next rank after the last fixed position. | ||||
|          */ | ||||
|         def safe(j:Long) { | ||||
|             for (k in 0..(fixed-1)) { | ||||
|                 if (j == q(k) || Math.abs(fixed-k) == Math.abs(j-q(k))) | ||||
|                     return false; | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         /** Search all positions for the current board. */ | ||||
|         def search() { | ||||
|             for (k in R) searchOne(k); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Modify the current board by adding a new queen | ||||
|          * in file <code>k</code> on rank <code>fixed</code>, | ||||
|          * and search for all safe positions with this prefix. | ||||
|          */ | ||||
|         def searchOne(k:Long) { | ||||
|             if (safe(k)) { | ||||
|                 if (fixed==(N-1)) { | ||||
|                     // all ranks safely filled | ||||
|                     atomic NQueensDist.this.results(here.id)++; | ||||
|                 } else { | ||||
|                     q(fixed++) = k; | ||||
|                     search(); | ||||
|                     fixed--; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Search this board, dividing the work between all places | ||||
|          * using a block distribution of the current free rank. | ||||
|          */ | ||||
|         def distSearch()  { | ||||
|             val work = R.split(Place.numPlaces()); | ||||
|             finish for (p in Place.places()) { | ||||
|                 val myPiece = work(p.id); | ||||
|                 at (p) async { | ||||
|                     // implicit copy of 'this' made across the at divide | ||||
|                     for (k in myPiece) { | ||||
|                         searchOne(k); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static def main(args:Rail[String])  { | ||||
|         val n = args.size > 0 ? Long.parse(args(0)) : 8; | ||||
|         Console.OUT.println("N=" + n); | ||||
|         //warmup | ||||
|         //finish new NQueensPar(12, 1).start(); | ||||
|         val P = Place.numPlaces(); | ||||
|         val nq = new NQueensDist(n,P); | ||||
|         var start:Long = -System.nanoTime(); | ||||
|         val answer = nq.run(); | ||||
|         val result = answer==EXPECTED_SOLUTIONS(n); | ||||
|         start += System.nanoTime(); | ||||
|         start /= 1000000; | ||||
|         Console.OUT.println("NQueensDist " + nq.N + "(P=" + P + | ||||
|                             ") has " + answer + " solutions" + | ||||
|                             (result? " (ok)." : " (wrong).") +  | ||||
|                             "time=" + start + "ms"); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										117
									
								
								samples/X10/NQueensPar.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								samples/X10/NQueensPar.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  *  (C) Copyright Australian National University 2011. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Compute the number of solutions to the N queens problem. | ||||
|  */ | ||||
| public class NQueensPar { | ||||
|     public static val EXPECTED_SOLUTIONS = | ||||
|         [0, 1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680, 14200, 73712, 365596, 2279184, 14772512]; | ||||
|  | ||||
|     val N:Int; | ||||
|     val P:Int; | ||||
|     var nSolutions:Int = 0n; | ||||
|     val R:IntRange; | ||||
|  | ||||
|     def this(N:Int, P:Int) {  | ||||
|        this.N=N; | ||||
|        this.P=P; | ||||
|        this.R = 0n..(N-1n); | ||||
|     } | ||||
|  | ||||
|     def start() { | ||||
|         new Board().parSearch(); | ||||
|     } | ||||
|  | ||||
|     class Board { | ||||
|         val q: Rail[Int]; | ||||
|         /** The number of low-rank positions that are fixed in this board for the purposes of search. */ | ||||
|         var fixed:Int; | ||||
|         def this() { | ||||
|             q = new Rail[Int](N); | ||||
|             fixed = 0n; | ||||
|         } | ||||
|  | ||||
|         def this(b:Board) { | ||||
|             this.q = new Rail[Int](b.q); | ||||
|             this.fixed = b.fixed; | ||||
|         } | ||||
|  | ||||
|         /**  | ||||
|          * @return true if it is safe to put a queen in file <code>j</code> | ||||
|          * on the next rank after the last fixed position. | ||||
|          */ | ||||
|         def safe(j:Int) { | ||||
|             for (k in 0n..(fixed-1n)) { | ||||
|                 if (j == q(k) || Math.abs(fixed-k) == Math.abs(j-q(k))) | ||||
|                     return false; | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         /** Search all positions for the current board. */ | ||||
|         def search() { | ||||
|             for (k in R) searchOne(k); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Modify the current board by adding a new queen | ||||
|          * in file <code>k</code> on rank <code>fixed</code>, | ||||
|          * and search for all safe positions with this prefix. | ||||
|          */ | ||||
|         def searchOne(k:Int) { | ||||
|             if (safe(k)) { | ||||
|                 if (fixed==(N-1n)) { | ||||
|                     // all ranks safely filled | ||||
|                     atomic NQueensPar.this.nSolutions++; | ||||
|                 } else { | ||||
|                     q(fixed++) = k; | ||||
|                     search(); | ||||
|                     fixed--; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Search this board, dividing the work between threads | ||||
|          * using a block distribution of the current free rank. | ||||
|          */ | ||||
|         def parSearch()  { | ||||
|             for (work in R.split(P)) async { | ||||
|                 val board = new Board(this); | ||||
|                 for (w in work) { | ||||
|                     board.searchOne(w); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static def main(args:Rail[String])  { | ||||
|         val n = args.size > 0 ? Int.parse(args(0)) : 8n; | ||||
|         Console.OUT.println("N=" + n); | ||||
|         //warmup | ||||
|         //finish new NQueensPar(12, 1).start(); | ||||
|         val ps = [1n,2n,4n]; | ||||
|         for (numTasks in ps) { | ||||
|             Console.OUT.println("starting " + numTasks + " tasks"); | ||||
|             val nq = new NQueensPar(n,numTasks); | ||||
|             var start:Long = -System.nanoTime(); | ||||
|             finish nq.start(); | ||||
|             val result = (nq.nSolutions as Long)==EXPECTED_SOLUTIONS(nq.N); | ||||
|             start += System.nanoTime(); | ||||
|             start /= 1000000; | ||||
|             Console.OUT.println("NQueensPar " + nq.N + "(P=" + numTasks + | ||||
|                     ") has " + nq.nSolutions + " solutions" + | ||||
|                     (result? " (ok)." : " (wrong).") + "time=" + start + "ms"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										73
									
								
								samples/X10/QSort.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								samples/X10/QSort.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Straightforward quicksort implementation using | ||||
|  * naive partition-in-the-middle and not bothering with | ||||
|  * well-known optimizations such as using insertion sort | ||||
|  * once the partitions get small.  This is only intended | ||||
|  * as a simple example of an array-based program that  | ||||
|  * combines a recirsive divide and conquer algorithm  | ||||
|  * with async and finish, not as a highly efficient  | ||||
|  * sorting procedure.. | ||||
|  */ | ||||
| public class QSort { | ||||
|  | ||||
|   private static def partition(data:Rail[int], left:long, right:long) { | ||||
|       var i:long = left; | ||||
|       var j:long = right; | ||||
|       var tmp:int; | ||||
|       var pivot:long = data((left + right) / 2); | ||||
|  | ||||
|       while (i <= j) { | ||||
|           while (data(i) < pivot) i++; | ||||
|           while (data(j) > pivot) j--; | ||||
|           if (i <= j) { | ||||
|               tmp = data(i); | ||||
|               data(i) = data(j); | ||||
|               data(j) = tmp; | ||||
|               i++; | ||||
|               j--; | ||||
|           } | ||||
|       } | ||||
|  | ||||
|       return i; | ||||
|   } | ||||
|  | ||||
|   public static def qsort(data:Rail[int], left:long, right:long) { | ||||
|       index:long = partition(data, left, right); | ||||
|       finish { | ||||
|           if (left < index - 1) | ||||
|               async qsort(data, left, index - 1); | ||||
|  | ||||
|           if (index < right) | ||||
|               qsort(data, index, right); | ||||
|       } | ||||
|   } | ||||
|  | ||||
|   public static def main(args:Rail[String]) { | ||||
|       val N = args.size>0 ? Long.parse(args(0)) : 100; | ||||
|       val r = new x10.util.Random(); | ||||
|       val data = new Rail[int](N, (long)=>r.nextInt(9999n)); | ||||
|       qsort(data, 0, N-1); | ||||
|       for (i in 0..(N-1)) { | ||||
|           Console.OUT.print(data(i));  | ||||
|           if (i%10 == 9) { | ||||
| 	      Console.OUT.println(); | ||||
|           } else { | ||||
|               Console.OUT.print(", "); | ||||
|           } | ||||
|       } | ||||
|       Console.OUT.println(); | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										123
									
								
								samples/X10/StructSpheres.x10
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								samples/X10/StructSpheres.x10
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| /* | ||||
|  *  This file is part of the X10 project (http://x10-lang.org). | ||||
|  * | ||||
|  *  This file is licensed to You under the Eclipse Public License (EPL); | ||||
|  *  You may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  *      http://www.opensource.org/licenses/eclipse-1.0.php | ||||
|  * | ||||
|  *  (C) Copyright IBM Corporation 2006-2014. | ||||
|  */ | ||||
|  | ||||
| import x10.io.Console; | ||||
| import x10.util.Random; | ||||
|  | ||||
| /** | ||||
|  * This class represents a real-world problem in graphics engines -- | ||||
|  * determining which objects in a large sprawling world are close enough to the | ||||
|  * camera to be considered for rendering.   | ||||
|  * | ||||
|  * It illustrates the usage of X10 structs to define new primitive types. | ||||
|  * In Native X10, structs are allocated within their containing object/stack frame | ||||
|  * and thus using structs instead of classes for Vector3 and WorldObject greatly | ||||
|  * improves the memory efficiency of the computation. | ||||
|  * | ||||
|  * @Author Dave Cunningham | ||||
|  * @Author Vijay Saraswat | ||||
|  */ | ||||
| class StructSpheres { | ||||
|     static type Real = Float; | ||||
|  | ||||
|     static struct Vector3(x:Real, y:Real, z:Real) { | ||||
|         public def getX () = x;  | ||||
|         public def getY () = y; | ||||
|         public def getZ () = z; | ||||
|  | ||||
|         public def add (other:Vector3) | ||||
|             = Vector3(this.x+other.x, this.y+other.y, this.z+other.z); | ||||
|  | ||||
|         public def neg () = Vector3(-this.x, -this.y, -this.z); | ||||
|  | ||||
|         public def sub (other:Vector3) = add(other.neg()); | ||||
|  | ||||
|         public def length () = Math.sqrtf(length2()); | ||||
|  | ||||
|         public def length2 () = x*x + y*y + z*z; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     static struct WorldObject { | ||||
|  | ||||
|         def this (x:Real, y:Real, z:Real, r:Real) { | ||||
|             pos = Vector3(x,y,z); | ||||
|             renderingDistance = r; | ||||
|         } | ||||
|  | ||||
|         public def intersects (home:Vector3) | ||||
|             = home.sub(pos).length2() < renderingDistance*renderingDistance; | ||||
|  | ||||
|         protected val pos:Vector3; | ||||
|         protected val renderingDistance:Real; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public static def compute():boolean { | ||||
|  | ||||
|         val reps = 7500; | ||||
|  | ||||
|         // The following correspond to a modern out-door computer game: | ||||
|         val num_objects = 50000; | ||||
|         val world_size = 6000; | ||||
|         val obj_max_size = 400; | ||||
|  | ||||
|         val ran = new Random(0); | ||||
|  | ||||
|         // the array can go on the heap | ||||
|         // but the elements ought to be /*inlined*/ in the array | ||||
|         val spheres = | ||||
|             new Rail[WorldObject](num_objects, (i:long) => { | ||||
|                 val x = (ran.nextDouble()*world_size) as Real; | ||||
|                 val y = (ran.nextDouble()*world_size) as Real; | ||||
|                 val z = (ran.nextDouble()*world_size) as Real; | ||||
|                 val r = (ran.nextDouble()*obj_max_size) as Real; | ||||
|                 return WorldObject(x,y,z,r); | ||||
|             }); | ||||
|  | ||||
|         val time_start = System.nanoTime(); | ||||
|  | ||||
|         var counter : Long = 0; | ||||
|  | ||||
|         // HOT LOOP BEGINS | ||||
|         for (c in 1..reps) { | ||||
|  | ||||
|             val x = (ran.nextDouble()*world_size) as Real; | ||||
|             val y = (ran.nextDouble()*world_size) as Real; | ||||
|             val z = (ran.nextDouble()*world_size) as Real; | ||||
|  | ||||
|             val pos = Vector3(x,y,z); | ||||
|  | ||||
|             for (i in spheres.range()) { | ||||
|                 if (spheres(i).intersects(pos)) { | ||||
|                     counter++; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         // HOT LOOP ENDS | ||||
|  | ||||
|         val time_taken = System.nanoTime() - time_start; | ||||
|         Console.OUT.println("Total time: "+time_taken/1E9); | ||||
|  | ||||
|         val expected = 109702; | ||||
|         val ok = counter == expected; | ||||
|         if (!ok) { | ||||
|             Console.ERR.println("number of intersections: "+counter | ||||
|                                 +" (expected "+expected+")"); | ||||
|         } | ||||
|         return ok; | ||||
|     } | ||||
|  | ||||
|     public static def main (Rail[String]) { | ||||
|         compute(); | ||||
|     } | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user