00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <oned/rec_bisect.hpp>
00038
00039 template<typename T, typename Pr>
00040 double oned::RecursiveBisection<T, Pr>::calculateDiff(const Pr& prefixSum, int low, int high,
00041 int leftProc, int rightProc, int candidate)
00042 {
00043 assert(low>0);
00044 assert(candidate>=0);
00045
00046
00047 double a = (prefixSum[candidate] - prefixSum[low - 1]) / ((double)leftProc);
00048 double b = (prefixSum[high] - prefixSum[candidate])/ ((double)rightProc);
00049
00050 return (a>b?a:b);
00051 }
00052
00053 template<typename T, typename Pr>
00054 int oned::RecursiveBisection<T, Pr>::findEvenCut(const Pr& prefixSum, int low, int high, int leftProc, int rightProc)
00055 {
00056 using namespace util;
00057 assert (low<=high);
00058 assert(leftProc != 0);
00059 assert(rightProc != 0);
00060 assert (low>0);
00061 if (debugFEC)
00062 {
00063 std::cerr << "##findEvenCut(" << low << " " << high << " " << leftProc << " " << rightProc << ")" << std::endl;
00064 }
00065
00066
00067 T cutWeight = (T) ((prefixSum[high] - prefixSum[low - 1]) * (double)leftProc / ((double)leftProc + (double)rightProc));
00068 int cutPoint = binarySearch(prefixSum, low, high, cutWeight+prefixSum[low-1]);
00069
00070 if (debugFEC)
00071 {
00072 std::cerr << cutWeight << " " << cutPoint << std::endl;
00073 }
00074
00075
00076 if (cutPoint == -1)
00077 return low;
00078 double d1 = calculateDiff (prefixSum, low, high, leftProc, rightProc, cutPoint);
00079 double d2 = calculateDiff (prefixSum, low, high, leftProc, rightProc, cutPoint+1);
00080
00081 assert (cutPoint >= low);
00082 assert (cutPoint <= high);
00083 return d1 < d2 ? cutPoint : cutPoint+1;
00084 }
00085
00086
00087
00088 template<typename T, typename Pr>
00089 T oned::RecursiveBisection<T, Pr>::rec_bisection_internal(int numProc, int low, int high, const Pr& prefixSum, int *cutPoints)
00090 {
00091 using namespace util;
00092 int leftProc, rightProc, cutPointHere, candidate1, candidate2;
00093 T candidate1diff, candidate2diff;
00094
00095 if (debugRB)
00096 {
00097 std::cerr << "**rec_bisection_internal(" << numProc << " " <<low << " " <<high << " " << cutPoints << ")" << std::endl;
00098 }
00099
00100 if(low > high)
00101 {
00102 int p;
00103 for (p = 0;p<numProc - 1;p++)
00104 {
00105 cutPoints[p] = high;
00106 }
00107 return 0;
00108 }
00109
00110
00111 assert (prefixSum[high-1]<=prefixSum[high]);
00112 assert (prefixSum[low]<=prefixSum[high]);
00113 assert (numProc>0);
00114
00115 if (numProc == 1)
00116 {
00117 if (debugRB)
00118 {
00119 std::cerr << "numProc==1, load = " << prefixSum[high] - prefixSum[low - 1] << ", prefixSum[high] = " << prefixSum[high] << ", prefixSum[low-1] = " << prefixSum[low-1] << ", high = " << high << ", low = " <<low << std::endl;
00120 }
00121
00122 return prefixSum[high] - prefixSum[low-1];
00123 }
00124
00125
00126 if (high-low+1 <= numProc)
00127 {
00128 int p;
00129 T m=prefixSum[low] - prefixSum[low - 1];
00130
00131 if (debugRB)
00132 {
00133 fprintf (stderr, "high-low+1 <= numProc; m = %lf\n",m);
00134 }
00135
00136
00137
00138 for (p = 0;p < high-low; p++)
00139 {
00140 cutPoints[p] = low+p;
00141 m = std::max(m, prefixSum[low+p] - prefixSum[low+p-1]);
00142 }
00143
00144 for (;p<numProc - 1;p++)
00145 {
00146 cutPoints[p] = high;
00147 }
00148
00149 if (debugRB)
00150 {
00151 fprintf (stderr,
00152 "load = %lf\n", m);
00153 }
00154
00155
00156 return m;
00157 }
00158
00159 if(numProc > 1)
00160 {
00161 leftProc = (numProc >> 1);
00162 rightProc = numProc - leftProc;
00163
00164
00165
00166 assert(leftProc != 0);
00167 assert(rightProc != 0);
00168 candidate1 = findEvenCut(prefixSum, low, high, leftProc, rightProc);
00169 candidate2 = findEvenCut(prefixSum, low, high, rightProc, leftProc);
00170
00171 assert (candidate1<=high);
00172 assert (candidate1>=low);
00173 assert (candidate2<=high);
00174 assert (candidate2>=low);
00175
00176 candidate1diff = calculateDiff(prefixSum, low, high, leftProc, rightProc, candidate1);
00177 if (leftProc != rightProc)
00178 candidate2diff = calculateDiff(prefixSum, low, high, rightProc, leftProc, candidate2);
00179 else
00180 candidate2diff = candidate1diff*2;
00181
00182 if (debugRB)
00183 {
00184 fprintf (stderr,
00185 "left/right = %d/%lf, right/left = %d/%lf\n",
00186 candidate1, candidate1diff,
00187 candidate2, candidate2diff);
00188 }
00189
00190
00191 if (candidate1diff < candidate2diff)
00192 {
00193 cutPointHere = candidate1;
00194 }
00195 else
00196 {
00197
00198 cutPointHere = candidate2;
00199 int tmp = rightProc;
00200 rightProc = leftProc;
00201 leftProc = tmp;
00202 }
00203 if(cutPointHere == -1)
00204 cutPointHere = low;
00205 assert(cutPointHere > -1);
00206
00207 assert (cutPointHere<=high);
00208 assert (cutPointHere>=low);
00209
00210 *(cutPoints+leftProc-1) = cutPointHere;
00211 assert(cutPointHere >= low);
00212 assert(leftProc + rightProc == numProc);
00213 T a = rec_bisection_internal(leftProc, low, cutPointHere, prefixSum, cutPoints);
00214 T b = rec_bisection_internal(rightProc, cutPointHere+1, high, prefixSum, cutPoints+leftProc);
00215 return std::max(a,b);
00216 }
00217 assert (0);
00218 return -1;
00219 }
00220
00221 template <typename T, typename Pr>
00222 T oned::RecursiveBisection<T, Pr>::rec_bisection(int procCount, const Pr& prefixSumArray,
00223 int length, int *cutIndexes, T )
00224 {
00225 return rec_bisection_internal(procCount, 1, length - 1, prefixSumArray, cutIndexes);
00226 }