Bladeren bron

Actually launch a worker thread and do some work.

Ian Goldberg 14 jaren geleden
bovenliggende
commit
d32933d9a3
2 gewijzigde bestanden met toevoegingen van 60 en 3 verwijderingen
  1. 2 2
      Makefile
  2. 58 1
      worker.cc

+ 2 - 2
Makefile

@@ -57,8 +57,8 @@ controller: controller.o evutils.o
 dpnode: dpnode.o evutils.o
 dpnode: dpnode.o evutils.o
 	g++ -g -Wall $^ -o $@ -L$(LIBEVENT)/lib -levent -lntl -L$(GMP) -lgmp
 	g++ -g -Wall $^ -o $@ -L$(LIBEVENT)/lib -levent -lntl -L$(GMP) -lgmp
 
 
-worker: worker.o evutils.o
-	g++ -g -Wall $^ -o $@ -L$(LIBEVENT)/lib -levent -lntl -L$(GMP) -lgmp -lpthread
+worker: worker.o evutils.o cudadl.o
+	g++ -g -Wall $^ -o $@ -L$(LIBEVENT)/lib -levent -lntl -L$(GMP) -lgmp -lpthread -L$(CUDA)/lib64 -lcudart
 
 
 clean:
 clean:
 	-rm -f $(OFILES)
 	-rm -f $(OFILES)

+ 58 - 1
worker.cc

@@ -4,13 +4,19 @@ extern "C" {
 #include <event2/event.h>
 #include <event2/event.h>
 }
 }
 
 
+#include <NTL/ZZ_p.h>
+
 #include <vector>
 #include <vector>
 #include <pthread.h>
 #include <pthread.h>
 #include <stdio.h>
 #include <stdio.h>
 
 
+#include "cudadl.h"
+
 #include "evutils.h"
 #include "evutils.h"
 #include "subproblem.h"
 #include "subproblem.h"
 
 
+NTL_CLIENT
+
 typedef enum {
 typedef enum {
     WRKCCSTATE_AWAITCMD,
     WRKCCSTATE_AWAITCMD,
     WRKCCSTATE_RDPROBLEM,
     WRKCCSTATE_RDPROBLEM,
@@ -39,6 +45,51 @@ static struct WrkControllerState {
 	worker_thread_state(WT_NOT_RUNNING) {}
 	worker_thread_state(WT_NOT_RUNNING) {}
 } wrkctrlstate;
 } wrkctrlstate;
 
 
+// ----- Below this line are the functions running in the worker thread.
+
+
+// This function is called from inside cuda_dl for each DP it encounters.
+// It calls the function named "dpcallback" directly.  It would be
+// cleaner if this were passed as a function pointer to cuda_dl, but
+// that makes nvcc 3.1 segfault. :-p
+bool dpcallback(void *cbdata, unsigned short threadId,
+    unsigned short blockId, unsigned int demux, unsigned int *dpwords,
+    unsigned int a_0, unsigned int a_1, unsigned int a_2,
+    unsigned int b_0, unsigned int b_1, unsigned int b_2)
+{
+    struct bufferevent *bev =
+	wrkctrlstate.dpnodes[demux % wrkctrlstate.num_connected_dpnodes];
+
+    unsigned char DPbuf[(WORDS+6)*sizeof(unsigned int)];
+    memmove(DPbuf, dpwords, WORDS*sizeof(unsigned int));
+    memmove(DPbuf+WORDS*sizeof(unsigned int), &a_0, sizeof(unsigned int));
+    memmove(DPbuf+(WORDS+1)*sizeof(unsigned int), &a_1, sizeof(unsigned int));
+    memmove(DPbuf+(WORDS+2)*sizeof(unsigned int), &a_2, sizeof(unsigned int));
+    memmove(DPbuf+(WORDS+3)*sizeof(unsigned int), &b_0, sizeof(unsigned int));
+    memmove(DPbuf+(WORDS+4)*sizeof(unsigned int), &b_1, sizeof(unsigned int));
+    memmove(DPbuf+(WORDS+5)*sizeof(unsigned int), &b_2, sizeof(unsigned int));
+    bufferevent_write(bev, DPbuf, (WORDS+6)*sizeof(unsigned int));
+
+    // If worker_thread_state changes to WT_SHOULD_STOP, then signal to
+    // stop computation by returning true.  If for some reason, it
+    // becomes WT_NOT_RUNNING (which it shouldn't), stop as well.
+    return wrkctrlstate.worker_thread_state != WT_RUNNING;
+}
+
+static void *worker_thread_start(void *data)
+{
+    ZZ_p::init(wrkctrlstate.current_problem->modulus);
+    cuda_dl(to_ZZ_p(wrkctrlstate.current_problem->base),
+	    to_ZZ_p(wrkctrlstate.current_problem->target),
+	    wrkctrlstate.current_problem->order,
+	    wrkctrlstate.current_problem->modulus, NULL);
+
+    return NULL;
+}
+
+// ----- Above this line are the functions running in the worker thread.
+//       Below are the functions running in the main (communication) thread.
+
 static void stop_working(void)
 static void stop_working(void)
 {
 {
     cerr << "Stopping work\n";
     cerr << "Stopping work\n";
@@ -67,6 +118,12 @@ static void stop_working(void)
 static void start_working(void)
 static void start_working(void)
 {
 {
     cerr << "Starting work\n";
     cerr << "Starting work\n";
+    wrkctrlstate.worker_thread_state = WT_RUNNING;
+    if (pthread_create(&wrkctrlstate.worker_thread, NULL,
+			worker_thread_start, NULL)) {
+	wrkctrlstate.worker_thread = WT_NOT_RUNNING;
+	cerr << "Could not start worker thread\n";
+    }
 }
 }
 
 
 static void dpconn_event_cb(struct bufferevent *bev, short events,
 static void dpconn_event_cb(struct bufferevent *bev, short events,
@@ -81,8 +138,8 @@ static void dpconn_event_cb(struct bufferevent *bev, short events,
 	}
 	}
     } else if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
     } else if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
 	fprintf(stderr, "Closing connection to dpnode\n");
 	fprintf(stderr, "Closing connection to dpnode\n");
-	bufferevent_free(bev);
 	stop_working();
 	stop_working();
+	bufferevent_free(bev);
     }
     }
 }
 }