mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			193 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			7.4 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.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
 |