mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +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();
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |