mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 09:40:21 +00:00
115 lines
4.2 KiB
Plaintext
115 lines
4.2 KiB
Plaintext
/*
|
|
* 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();
|
|
}
|
|
}
|
|
}
|