     checkCuda(cudaFree(deviceClusters));
     checkCuda(cudaFree(deviceMembership));
     checkCuda(cudaFree(deviceIntermediates));
-//  checkCuda(cudaFree(deviceNewClusterSize));
 
     free(dimObjects[0]);
     free(dimObjects);

        checkCuda(cudaMemcpy(&d, deviceIntermediates,
                  sizeof(int), cudaMemcpyDeviceToHost));
        delta = (float)d;
//      msg("%2d: delta = %d\n", loop, d)

//      checkCuda(cudaMemcpy(clusters[0], deviceClusters,
//            numClusters*numCoords*sizeof(float), cudaMemcpyDeviceToHost));
        checkCuda(cudaMemcpy(membership, deviceMembership,
                  numObjs*sizeof(int), cudaMemcpyDeviceToHost));
//      checkCuda(cudaMemcpy(newClusterSize, deviceNewClusterSize,
//                numClusters*sizeof(int), cudaMemcpyDeviceToHost));

        for (i=0; i<numObjs; i++) {
            /* find the array index of nestest cluster center */
            index = membership[i];
//          msg("membership[%d] = %d\n", i, membership[i])

            /* update new cluster centers : sum of objects located within */
            newClusterSize[index]++;

    float *deviceClusters;
    int *deviceMembership;
    int *deviceIntermediates;

    //  Copy objects given in [numObjs][numCoords] layout
    //  to new [numCoords][numObjs] layout
    malloc2D(dimObjects, numCoords, numObjs, float);
    for (i = 0; i < numCoords; i++) {
        for (j = 0; j < numObjs; j++) {
