9 /* =============================================================================
12 * -- Implementation of normal k-means clustering algorithm
14 * =============================================================================
19 * ECE Department, Northwestern University
20 * email: wkliao@ece.northwestern.edu
26 * Northwestern University.
32 * University of California, Irvine
35 * =============================================================================
37 * For the license of bayes/sort.h and bayes/sort.c, please see the header
40 * ------------------------------------------------------------------------
42 * For the license of kmeans, please see kmeans/LICENSE.kmeans
44 * ------------------------------------------------------------------------
46 * For the license of ssca2, please see ssca2/COPYRIGHT
48 * ------------------------------------------------------------------------
50 * For the license of lib/mt19937ar.c and lib/mt19937ar.h, please see the
51 * header of the files.
53 * ------------------------------------------------------------------------
55 * For the license of lib/rbtree.h and lib/rbtree.c, please see
56 * lib/LEGALNOTICE.rbtree and lib/LICENSE.rbtree
58 * ------------------------------------------------------------------------
60 * Unless otherwise noted, the following license applies to STAMP files:
62 * Copyright (c) 2007, Stanford University
63 * All rights reserved.
65 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions are
69 * * Redistributions of source code must retain the above copyright
70 * notice, this list of conditions and the following disclaimer.
72 * * Redistributions in binary form must reproduce the above copyright
73 * notice, this list of conditions and the following disclaimer in
74 * the documentation and/or other materials provided with the
77 * * Neither the name of Stanford University nor the names of its
78 * contributors may be used to endorse or promote products derived
79 * from this software without specific prior written permission.
81 * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY
82 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
84 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE
85 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
86 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
87 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
88 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
89 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
90 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
91 * THE POSSIBILITY OF SUCH DAMAGE.
93 * =============================================================================
104 * ==========================================================================
106 * ==================================================================
109 public static void work(int myId, GlobalArgs args) {
111 float[][] feature = args.feature;
112 int nfeatures = args.nfeatures;
113 int npoints = args.npoints;
114 int nclusters = args.nclusters;
115 int[] membership = args.membership;
116 float[][] clusters = args.clusters;
117 int[] new_centers_len = args.new_centers_len;
118 float[][] new_centers = args.new_centers;
123 start = myId * CHUNK;
125 while (start < npoints) {
126 stop = (((start + CHUNK) < npoints) ? (start + CHUNK) : npoints);
129 int indexArrayLen=stop-start;
130 int indexArray[]=new int[indexArrayLen];
132 for (int i = start; i < stop; i++) {
133 int index = Common.common_findNearestPoint(feature[i],
137 indexArray[pidx]=index;
145 for (int i = start; i < stop; i++) {
147 int newIndex=indexArray[sidx];
148 if (membership[i] != newIndex) {
152 membership[i] = newIndex;
153 new_centers_len[newIndex] = new_centers_len[newIndex] + 1;
155 float[] tmpnew_centers=new_centers[newIndex];
156 float[] tmpfeature=feature[i];
158 for (int j = 0; j < nfeatures; j++) {
159 tmpnew_centers[j] = tmpnew_centers[j] + tmpfeature[j];
168 if (start + CHUNK < npoints) {
170 start = args.global_i;
171 args.global_i = start + CHUNK;
180 while (start < npoints) {
181 stop = (((start + CHUNK) < npoints) ? (start + CHUNK) : npoints);
183 for (int i = start; i < stop; i++) {
186 int index = Common.common_findNearestPoint(feature[i],
194 // If membership changes, increase delta by 1.
195 // membership[i] cannot be changed by other threads
196 if (membership[i] != index) {
200 // Assign the membership to object i
201 // membership[i] can't be changed by other thread
202 membership[i] = index;
204 // Update new cluster centers : sum of objects located within
205 new_centers_len[index] = new_centers_len[index] + 1;
206 for (int j = 0; j < nfeatures; j++) {
207 new_centers[index][j] = new_centers[index][j] + feature[i][j];
214 if (start + CHUNK < npoints) {
215 start = args.global_i;
216 args.global_i = start + CHUNK;
222 args.global_delta = args.global_delta + delta;
226 * ==========================================================================
228 * ==========================================================
229 * ===================
231 public float[][] normal_exec(int nthreads, float[][] feature, /*
236 int nfeatures, int npoints, int nclusters, float threshold,
237 int[] membership, Random randomPtr, /* out: [npoints] */
240 float[][] clusters; /* out: [nclusters][nfeatures] */
242 /* Allocate space for returning variable clusters[] */
243 clusters = new float[nclusters][nfeatures];
245 /* Randomly pick cluster centers */
246 for (int i = 0; i < nclusters; i++) {
247 int n = (int) (randomPtr.random_generate() % npoints);
248 for (int j = 0; j < nfeatures; j++) {
249 clusters[i][j] = feature[n][j];
253 for (int i = 0; i < npoints; i++) {
258 * Need to initialize new_centers_len and new_centers[0] to all 0.
259 * Allocate clusters on different cache lines to reduce false sharing.
261 int[] new_centers_len = new int[nclusters];
263 float[][] new_centers = new float[nclusters][nfeatures];
267 long start = System.currentTimeMillis();
271 args.feature = feature;
272 args.nfeatures = nfeatures;
273 args.npoints = npoints;
274 args.nclusters = nclusters;
275 args.membership = membership;
276 args.clusters = clusters;
277 args.new_centers_len = new_centers_len;
278 args.new_centers = new_centers;
280 args.global_i = nthreads * CHUNK;
281 args.global_delta = delta;
283 // Work in parallel with other threads
285 delta = args.global_delta;
287 // put stall site here rather than having inside of loop
288 nclusters=clusters.length;
289 int newCenterLen=new_centers_len.length;
290 int new_centersLen=new_centers.length;
293 /* Replace old cluster centers with new_centers */
294 for (int i = 0; i < nclusters; i++) {
295 for (int j = 0; j < nfeatures; j++) {
296 if (new_centers_len[i] > 0) {
297 clusters[i][j] = new_centers[i][j] / new_centers_len[i];
299 new_centers[i][j] = (float) 0.0; /* set back to 0 */
301 new_centers_len[i] = 0; /* set back to 0 */
306 } while ((delta > threshold) && (loop++ < 500));
307 long stop = System.currentTimeMillis();
308 args.global_time += (stop - start);
314 * Work done by primary thread in parallel with other threads
316 void thread_work(GlobalArgs args) {
317 Normal.work(0, args); // threadId = 0 because primary thread
322 * =============================================================================
326 * =============================================================================