• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ClusterHash.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /****************************************************************************
00025 
00026   ClusterHash.cc
00027  ****************************************************************************/
00028 #include "P_Cluster.h"
00029 
00030 //
00031 // Configuration of the cluster hash function
00032 //
00033 // machineClusterHash  - whether or not the random number generators
00034 //                       are based on the machines or on the buckets
00035 // boundClusterHash    - whether or not we force a fixed number of buckets
00036 //                       to map to each machine
00037 // randClusterHash     - whether or not to use system rand(3C)
00038 //                       or a simple linear congruence random number
00039 //                       generator
00040 //
00041 // This produces very stable results (computation time ~.6 seconds) on
00042 // a UltraSparc at 143Mz.
00043 // These are only global for testing purposes.
00044 //
00045 bool machineClusterHash = true;
00046 bool boundClusterHash = false;
00047 bool randClusterHash = false;
00048 
00049 // This produces better speed for large numbers of machines > 18
00050 //
00051 // bool machineClusterHash = false;
00052 // bool boundClusterHash = true;
00053 // bool randClusterHash = true;
00054 
00055 
00056 
00057 //
00058 // Cluster Hash Table
00059 //
00060 // see Memo.ClusterHash for details
00061 //
00062 
00063 
00064 //
00065 // Linear Congruence Random number generator
00066 
00067 // Not very random, but it generates all the numbers
00068 // within 1 period which is all we need.
00069 //
00070 inline unsigned short
00071 next_rnd15(unsigned int *p)
00072 {
00073   unsigned int seed = *p;
00074   seed = 1103515145 * seed + 12345;
00075   seed = seed & 0x7FFF;
00076   *p = seed;
00077   return seed;
00078 }
00079 
00080 //
00081 // Build the hash table
00082 // This function is relatively expensive.
00083 // It costs: (g++ at -02)
00084 // ~.04 CPU seconds on a 143MHz Ultra 1 at 1 node
00085 // ~.3 CPU seconds on a 143MHz Ultra 1 at 31 nodes
00086 // Overall it is roughly linear in the number of nodes.
00087 //
00088 void
00089 build_hash_table_machine(ClusterConfiguration * c)
00090 {
00091   int left = CLUSTER_HASH_TABLE_SIZE;
00092   int m = 0;
00093   int i = 0;
00094   unsigned int rnd[CLUSTER_MAX_MACHINES];
00095   unsigned int mach[CLUSTER_MAX_MACHINES];
00096   int total = CLUSTER_HASH_TABLE_SIZE;
00097 
00098   for (i = 0; i < c->n_machines; i++) {
00099     int mine = total / (c->n_machines - i);
00100     mach[i] = mine;
00101     total -= mine;
00102   }
00103 
00104   // seed the random number generator with the ip address
00105   // do a little xor folding to get it into 15 bits
00106   //
00107   for (m = 0; m < c->n_machines; m++)
00108     rnd[m] = (((c->machines[m]->ip >> 15) & 0x7FFF) ^ (c->machines[m]->ip & 0x7FFF))
00109       ^ (c->machines[m]->ip >> 30);
00110 
00111   // Initialize the table to "empty"
00112   //
00113   for (i = 0; i < CLUSTER_HASH_TABLE_SIZE; i++)
00114     c->hash_table[i] = 255;
00115 
00116   // Until we have hit every element of the table, give each
00117   // machine a chance to select it's favorites.
00118   //
00119   m = 0;
00120   while (left) {
00121     if (!mach[m] && boundClusterHash) {
00122       m = (m + 1) % c->n_machines;
00123       continue;
00124     }
00125     do {
00126       if (randClusterHash) {
00127         i = ink_rand_r(&rnd[m]) % CLUSTER_HASH_TABLE_SIZE;
00128       } else
00129         i = next_rand(&rnd[m]) % CLUSTER_HASH_TABLE_SIZE;
00130     } while (c->hash_table[i] != 255);
00131     mach[m]--;
00132     c->hash_table[i] = m;
00133     left--;
00134     m = (m + 1) % c->n_machines;
00135   }
00136 }
00137 
00138 static void
00139 build_hash_table_bucket(ClusterConfiguration * c)
00140 {
00141   int i = 0;
00142   unsigned int rnd[CLUSTER_HASH_TABLE_SIZE];
00143   unsigned int mach[CLUSTER_MAX_MACHINES];
00144   int total = CLUSTER_HASH_TABLE_SIZE;
00145 
00146   for (i = 0; i < c->n_machines; i++) {
00147     int mine = total / (c->n_machines - i);
00148     mach[i] = mine;
00149     total -= mine;
00150   }
00151 
00152   for (i = 0; i < CLUSTER_HASH_TABLE_SIZE; i++)
00153     rnd[i] = i;
00154 
00155   for (i = 0; i < CLUSTER_HASH_TABLE_SIZE; i++) {
00156     unsigned char x = 0;
00157     do {
00158       if (randClusterHash) {
00159         x = ink_rand_r(&rnd[i]) % CLUSTER_MAX_MACHINES;
00160       } else
00161         x = next_rand(&rnd[i]) % CLUSTER_MAX_MACHINES;
00162     } while (x >= c->n_machines || (!mach[x] && boundClusterHash));
00163     mach[x]--;
00164     c->hash_table[i] = x;
00165   }
00166 }
00167 
00168 void
00169 build_cluster_hash_table(ClusterConfiguration * c)
00170 {
00171   if (machineClusterHash)
00172     build_hash_table_machine(c);
00173   else
00174     build_hash_table_bucket(c);
00175 }

Generated by  doxygen 1.7.1