diff --git a/.gitmodules b/.gitmodules
index 35cc9de8..5f07d011 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -674,3 +674,6 @@
[submodule "vendor/grammars/sublime-typescript"]
path = vendor/grammars/sublime-typescript
url = https://github.com/Microsoft/TypeScript-Sublime-Plugin
+[submodule "vendor/grammars/X10"]
+ path = vendor/grammars/X10
+ url = git@github.com:x10-lang/x10-highlighting.git
diff --git a/grammars.yml b/grammars.yml
index ae9ff92c..42be3967 100644
--- a/grammars.yml
+++ b/grammars.yml
@@ -144,6 +144,8 @@ vendor/grammars/VBDotNetSyntax:
- source.vbnet
vendor/grammars/Vala-TMBundle:
- source.vala
+vendor/grammars/X10:
+- source.x10
vendor/grammars/abap.tmbundle:
- source.abap
vendor/grammars/actionscript3-tmbundle:
diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml
index 5b31ed4f..311c8d79 100644
--- a/lib/linguist/languages.yml
+++ b/lib/linguist/languages.yml
@@ -3567,6 +3567,16 @@ WebIDL:
tm_scope: source.webidl
ace_mode: text
+X10:
+ type: programming
+ aliases:
+ - xten
+ ace_mode: text
+ extensions:
+ - .x10
+ color: "#4B6BEF"
+ tm_scope: source.x10
+
XC:
type: programming
color: "#99DA07"
diff --git a/samples/X10/ArraySum.x10 b/samples/X10/ArraySum.x10
new file mode 100644
index 00000000..389d0e87
--- /dev/null
+++ b/samples/X10/ArraySum.x10
@@ -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)");
+ }
+ }
+}
diff --git a/samples/X10/Cancellation.x10 b/samples/X10/Cancellation.x10
new file mode 100644
index 00000000..1e13bea1
--- /dev/null
+++ b/samples/X10/Cancellation.x10
@@ -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");
+ }
+}
diff --git a/samples/X10/Fibonacci.x10 b/samples/X10/Fibonacci.x10
new file mode 100644
index 00000000..fc1466f1
--- /dev/null
+++ b/samples/X10/Fibonacci.x10
@@ -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
+ * async and finish in a
+ * prototypical recursive divide-and-conquer algorithm.
+ * It is obviously not intended to show a efficient way to
+ * compute Fibonacci numbers in X10.
+ *
+ * The heart of the example is the run method,
+ * which directly embodies the recursive definition of
+ *
+ * fib(n) = fib(n-1)+fib(n-2); + *+ * by using an
async to compute fib(n-1) while
+ * the current activity computes fib(n-2). A finish
+ * is used to ensure that both computations are complete before
+ * their results are added together to compute fib(n)
+ */
+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);
+ }
+}
+
diff --git a/samples/X10/HeatTransfer_v0.x10 b/samples/X10/HeatTransfer_v0.x10
new file mode 100644
index 00000000..5546fae8
--- /dev/null
+++ b/samples/X10/HeatTransfer_v0.x10
@@ -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();
+ }
+ }
+}
diff --git a/samples/X10/HeatTransfer_v1.x10 b/samples/X10/HeatTransfer_v1.x10
new file mode 100644
index 00000000..feeeebe6
--- /dev/null
+++ b/samples/X10/HeatTransfer_v1.x10
@@ -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();
+ }
+ }
+}
diff --git a/samples/X10/HelloWholeWorld.x10 b/samples/X10/HelloWholeWorld.x10
new file mode 100644
index 00000000..4017ef9d
--- /dev/null
+++ b/samples/X10/HelloWholeWorld.x10
@@ -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"
+ * + * 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]$ + *+ */ +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"); + } +} + + diff --git a/samples/X10/HelloWorld.x10 b/samples/X10/HelloWorld.x10 new file mode 100644 index 00000000..06743b4c --- /dev/null +++ b/samples/X10/HelloWorld.x10 @@ -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!" ); + } +} + + diff --git a/samples/X10/Histogram.x10 b/samples/X10/Histogram.x10 new file mode 100644 index 00000000..bf6ad2b1 --- /dev/null +++ b/samples/X10/Histogram.x10 @@ -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."); + } + } +} diff --git a/samples/X10/Integrate.x10 b/samples/X10/Integrate.x10 new file mode 100644 index 00000000..accf31b9 --- /dev/null +++ b/samples/X10/Integrate.x10 @@ -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. + *
+ * 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); + } +} diff --git a/samples/X10/KMeans.x10 b/samples/X10/KMeans.x10 new file mode 100644 index 00000000..475732b7 --- /dev/null +++ b/samples/X10/KMeans.x10 @@ -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. + *
+ * 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
diff --git a/samples/X10/KMeansDist.x10 b/samples/X10/KMeansDist.x10
new file mode 100644
index 00000000..069cc374
--- /dev/null
+++ b/samples/X10/KMeansDist.x10
@@ -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
diff --git a/samples/X10/KMeansDistPlh.x10 b/samples/X10/KMeansDistPlh.x10
new file mode 100644
index 00000000..ca16aa59
--- /dev/null
+++ b/samples/X10/KMeansDistPlh.x10
@@ -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
diff --git a/samples/X10/KMeansSPMD.x10 b/samples/X10/KMeansSPMD.x10
new file mode 100644
index 00000000..f6530f24
--- /dev/null
+++ b/samples/X10/KMeansSPMD.x10
@@ -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
diff --git a/samples/X10/MontyPi.x10 b/samples/X10/MontyPi.x10
new file mode 100644
index 00000000..951161ee
--- /dev/null
+++ b/samples/X10/MontyPi.x10
@@ -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 j
+ * 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 k on rank fixed,
+ * 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");
+ }
+}
diff --git a/samples/X10/NQueensPar.x10 b/samples/X10/NQueensPar.x10
new file mode 100644
index 00000000..bb841e13
--- /dev/null
+++ b/samples/X10/NQueensPar.x10
@@ -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 j
+ * 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 k on rank fixed,
+ * 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");
+ }
+ }
+}
diff --git a/samples/X10/QSort.x10 b/samples/X10/QSort.x10
new file mode 100644
index 00000000..d96983b6
--- /dev/null
+++ b/samples/X10/QSort.x10
@@ -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();
+ }
+}
+
diff --git a/samples/X10/StructSpheres.x10 b/samples/X10/StructSpheres.x10
new file mode 100644
index 00000000..6d833633
--- /dev/null
+++ b/samples/X10/StructSpheres.x10
@@ -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();
+ }
+
+}
diff --git a/vendor/grammars/X10 b/vendor/grammars/X10
new file mode 160000
index 00000000..05fc5c81
--- /dev/null
+++ b/vendor/grammars/X10
@@ -0,0 +1 @@
+Subproject commit 05fc5c81cc9491f5785e896c9a5f43a61fac9073