Explorar o código

Try to better calculate the needed resources to solve a subproblem

It looks OK, except it doesn't yet reduce the dpfreq if the number of
dpnodes we need exceeds the number of nodes available.
Ian Goldberg %!s(int64=14) %!d(string=hai) anos
pai
achega
2a4512a4ef
Modificáronse 2 ficheiros con 60 adicións e 7 borrados
  1. 3 0
      Makefile
  2. 57 7
      controller_main.cc

+ 3 - 0
Makefile

@@ -64,6 +64,9 @@ dpnode: dpnode.o evutils.o dpnode_main.o
 worker: worker.o evutils.o cudadl.o worker_main.o
 	g++ -g -Wall $^ -o $@ -L$(LIBEVENT)/lib -Wl,-rpath=$(LIBEVENT)/lib -levent -levent_pthreads -lntl -L$(GMP) -lgmp -lpthread -L$(CUDA)/lib64 -lcudart
 
+desres: controller_main.cc
+	g++ $(CXXFLAGS) $(CPPFLAGS) -DTEST_DESIRED_RESOURCES $^ -o $@ -L$(LIBEVENT)/lib -Wl,-rpath=$(LIBEVENT)/lib -lntl -lgmp
+
 mpi: mpi.o
 	mpiCC -g -Wall $^ -o $@ -L/work/iang/sw/lib -lntl -L$(GMP) -lgmp -lpthread
 

+ 57 - 7
controller_main.cc

@@ -17,24 +17,48 @@ static unsigned short GB_mem_per_node = 0;
 void desired_resources(const ZZ &order, unsigned short &desired_dpnodes,
     unsigned int &max_workers, unsigned int &dpfreq)
 {
+    // One point in how many is a DP by default?
+    unsigned int dpscale = 1000;
+    ZZ sorder = SqrRoot(order);
+
     // How many DPnodes should we use for a problem of this size?
     desired_dpnodes = 1;
+    // 338 is bytes per DP in the table.  10 is a safety factor.
+    ZZ dpnumerator = sorder * 338 * 10;
+    ZZ dpdenominator;
+    dpdenominator = dpscale;
+    dpdenominator *= GB_mem_per_node;
+    dpdenominator *= 1000000000UL;  // Convert the above line to GB
+    ZZ dpnodes = (dpnumerator / dpdenominator) + 1;
+    if (dpnodes > total_nodes) {
+	desired_dpnodes = total_nodes;
+    } else {
+	desired_dpnodes = trunc_long(dpnodes, 31);
+    }
+
     // How many workers would we like to use?
-    ZZ sorder = SqrRoot(order >> 46);
-    if (NumBits(sorder) > 30) {
+    ZZ sorder23 = sorder >> 23;
+    if (NumBits(sorder23) > 30) {
 	// Just use all the workers we can find
 	max_workers = 4294967295U;  // 2^32 - 1
     } else {
-	max_workers = trunc_long(sorder,31) + 1;
+	max_workers = trunc_long(sorder23,31) + 1;
     }
 
-    // By default, 1 in 1000 points are distinguihed points.  The
-    // number in the next line is 2^32/1000
-    dpfreq = 4294967;
+    // By default, 1 in dpscale points are distinguished points.
+    dpfreq = 4294967295U / dpscale;
+
+    // Orders smaller than 100*scale^2 behave specially, in order to
+    // avoid DP-free cycles
+    ZZ orderlimit;
+    orderlimit = 100;
+    orderlimit *= dpscale;
+    orderlimit *= dpscale;
+
     if (order < 1000) {
 	// Just make every point a DP
 	dpfreq = 4294967295U;
-    } else if (NumBits(order) < 27) {
+    } else if (order < orderlimit) {
 	// The frequency of DPs should be 10/sqrt(order) to avoid
 	// a DP-free cycle, so dpfreq = (10*2^32)/sqrt(order)
 	ZZ f = (to_ZZ(10) << 32) / SqrRoot(order);
@@ -56,6 +80,31 @@ static void boundcb(const char *boundaddr, unsigned short boundport)
     }
 }
 
+#ifdef TEST_DESIRED_RESOURCES
+int main(int argc, char **argv)
+{
+    if (argc != 3) {
+	std::cerr << "Usage: " << argv[0] << " num_nodes GB_mem_per_node\n";
+	return 1;
+    }
+
+    total_nodes = strtoul(argv[1], NULL, 10);
+    GB_mem_per_node = strtoul(argv[2], NULL, 10);
+    cout << "# log_2(order) dpnodes workers dpfreq\n";
+    for (int i=44; i<=90; ++i) {
+	unsigned short desired_dpnodes;
+	unsigned int max_workers;
+	unsigned int dpfreq;
+	ZZ order;
+	order = 1;
+	order <<= i;
+	order += 1;
+	desired_resources(order, desired_dpnodes, max_workers, dpfreq);
+	cout << i << " " << desired_dpnodes << " " << max_workers << " "
+		<< dpfreq << "\n";
+    }
+}
+#else
 int main(int argc, char **argv)
 {
     unsigned short bindport = 0;
@@ -69,3 +118,4 @@ int main(int argc, char **argv)
 
     return controller_main(worklist, bindport, boundcb);
 }
+#endif