Browse Source

Run dem_discr in another process

Olivier Marty 8 years ago
parent
commit
f4ff021fd3
4 changed files with 88 additions and 8 deletions
  1. 1 0
      .gitignore
  2. 6 3
      src/Makefile
  3. 4 0
      src/main.cpp
  4. 77 5
      src/pointset.cpp

+ 1 - 0
.gitignore

@@ -26,3 +26,4 @@ main.pdf
 *.o
 /src/main
 /src/dump
+/src/discr_calc/*_discr

+ 6 - 3
src/Makefile

@@ -1,8 +1,11 @@
 CPP=g++ -Wall -O2
 CC=gcc
 
-main: discr_calc/dem_discr.o discr_calc/bz_discr.o pointset.o permutation.o halton.o search.o main.o
-	$(CPP) $^ -o $@
+main: discr_calc/dem_discr pointset.o permutation.o halton.o search.o main.o
+	$(CPP) pointset.o permutation.o halton.o search.o main.o -o $@
+
+discr_calc/dem_discr:
+	$(MAKE) -C discr_calc dem_discr
 
 %.o: %.cpp
 	$(CPP) -c $< -o $@
@@ -13,4 +16,4 @@ main: discr_calc/dem_discr.o discr_calc/bz_discr.o pointset.o permutation.o halt
 .PHONY: clean
 
 clean:
-	rm -f *.o discr_calc/*.o main
+	rm -f *.o discr_calc/*.o discr_calc/*_discr main

+ 4 - 0
src/main.cpp

@@ -13,6 +13,10 @@ int main(int argc, char **argv) {
   int p[] = {7,13};
   assert(sizeof(p)/sizeof(int) == dim);
 
+  printf("npoints = %d\ndim = %d\np = ", npoints, dim);
+  for(int i = 0; i < dim; i++)
+    printf("%d%s", p[i], (i==dim-1) ? "\n\n" : ", ");
+
   random_search rs(dim, npoints, p);
   rs.run(1000);
 

+ 77 - 5
src/pointset.cpp

@@ -1,9 +1,15 @@
 #include "pointset.h"
 #include <cassert>
 
-extern "C" {
-  #include "discr_calc/dem_discr.h"
-}
+// for subprocesses
+#include <cstdlib>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+// extern "C" {
+//   #include "discr_calc/dem_discr.h"
+// }
 
 pointset::pointset(int dim, int npoints) : dim(dim), npoints(npoints) {
   assert(dim > 0);
@@ -25,8 +31,74 @@ double* pointset::point(int i) {
 }
 
 double pointset::discrepancy() {
-  double lower;
-  return oydiscr(data, dim, npoints, &lower);
+  //double lower;
+  // return oydiscr(data, dim, npoints, &lower);
+  // TODO appeler directement oydiscr ne semble pas marcher correctement
+  // il doit probablement falloir réinitialiser les variables globales (erk!)
+
+  // en attendant on lance un nouveau processus à chaque fois :
+  double result;
+  int status = -1, pid;
+  int pipefd_in[2], pipefd_out[2], null; // in/out : from parent's point of view
+  if(pipe(pipefd_in) || pipe(pipefd_out)) {
+    perror("pipe()");
+    exit(1);
+  }
+  switch(pid = fork()) {
+    case -1: // error
+      perror("fork()");
+      exit(1);
+    case 0: // child
+      close(pipefd_in[0]);
+      close(pipefd_out[1]);
+      // replace stdin
+      dup2(pipefd_out[0], 0);
+      // replace stdout
+      dup2(pipefd_in[1], 1);
+      // replace stderr :P
+      null = open("/dev/null", O_RDONLY);
+      dup2(null, 2);
+      close(null);
+      // launch process !
+      char dim_str[20], npoints_str[20];
+      sprintf(dim_str, "%d", dim);
+      sprintf(npoints_str, "%d", npoints);
+      execl("discr_calc/dem_discr", "dem_discr", dim_str, npoints_str, (char*)NULL);
+      // if we get to this line, the command has failed
+      perror("execl()");
+      exit(1);
+    default: // father
+      close(pipefd_in[1]);
+      close(pipefd_out[0]);
+      // write data into pipefd_in
+      FILE *f = fdopen(pipefd_out[1], "w");
+      if(f == NULL) {
+        perror("fdopen()");
+        exit(1);
+      }
+      dump(f);
+      fclose(f);
+      close(pipefd_out[1]);
+      // read result
+      f = fdopen(pipefd_in[0], "r");
+      if(f == NULL) {
+        perror("fdopen()");
+        exit(1);
+      }
+      if(fscanf(f, "%lf", &result) != 1) {
+        perror("fscanf()");
+        exit(1);
+      }
+      fclose(f);
+      close(pipefd_in[0]);
+      // wait for child to terminate
+      waitpid(pid, &status, 0);
+      if(status != 0) {
+        fprintf(stderr, "child process terminate with status %d\n", status);
+        exit(1);
+      }
+  }
+  return result;
 }
 
 void pointset::dump(FILE* f) {