Просмотр исходного кода

Make a test_cuda target that does a single subproblem without forking

Ian Goldberg 13 лет назад
Родитель
Сommit
cb74c97417
2 измененных файлов с 84 добавлено и 8 удалено
  1. 3 0
      Makefile
  2. 81 8
      parrhoasm.cu

+ 3 - 0
Makefile

@@ -52,6 +52,9 @@ dlrho.o: dlrho.cc
 cudadl.o: parrhoasm.cu cios.asm dpstream.cu
 cudadl.o: parrhoasm.cu cios.asm dpstream.cu
 	$(NVCC) $(CPPFLAGS) -c parrhoasm.cu -DWORDS=$(WORDS) -o cudadl.o
 	$(NVCC) $(CPPFLAGS) -c parrhoasm.cu -DWORDS=$(WORDS) -o cudadl.o
 
 
+test_cuda: parrhoasm.cu cios.asm dpstream.cu
+	$(NVCC) -DTEST_CUDA $(CPPFLAGS) parrhoasm.cu -DWORDS=$(WORDS) -o test_cuda -lntl -L$(GMP)/lib -lgmp -L$(CUDA)/lib64 -lcudart
+
 cios.asm: gencios_reg_20
 cios.asm: gencios_reg_20
 	./gencios_reg_20 $(WORDS) > $@
 	./gencios_reg_20 $(WORDS) > $@
 
 

+ 81 - 8
parrhoasm.cu

@@ -33,7 +33,7 @@
 
 
 // #define CHECK_RESULTS
 // #define CHECK_RESULTS
 
 
-// #define VERBOSE
+ #define VERBOSE
 
 
 // #include "cuPrintf.cu"
 // #include "cuPrintf.cu"
 
 
@@ -475,10 +475,10 @@ void cuda_dl(const ZZ_p &base, const ZZ_p &target, const ZZ &order,
     dim3 tpb(threadDimx, threadsPerBlock/threadDimx);
     dim3 tpb(threadDimx, threadsPerBlock/threadDimx);
     gettimeofday(&st, NULL);
     gettimeofday(&st, NULL);
     int launchcount = 0;
     int launchcount = 0;
+    bool stop_computing = false;
 #ifdef CHECK_RESULTS
 #ifdef CHECK_RESULTS
-    for (int ln=0; ln<nlaunch; ++ln)
+    for (int ln=0; ln<nlaunch && stop_computing == false; ++ln)
 #else
 #else
-    bool stop_computing = false;
     while(stop_computing == false)
     while(stop_computing == false)
 #endif
 #endif
     {
     {
@@ -523,8 +523,8 @@ cout << i << ": " << l_Z[i] << " != " << l_z[i + t * WORDS] << "\n";
 	    dump("d_z", l_Z, WORDS);
 	    dump("d_z", l_Z, WORDS);
 	    dump("l_z", l_z + t * WORDS, WORDS);
 	    dump("l_z", l_z + t * WORDS, WORDS);
 	}
 	}
-	ZZ ares = (to_ZZ(l_ts[t].a[1]) << 32) + to_ZZ(l_ts[t].a[0]);
-	ZZ bres = (to_ZZ(l_ts[t].b[1]) << 32) + to_ZZ(l_ts[t].b[0]);
+	ZZ ares = (to_ZZ(l_ts[t].a[2]) << 64) + (to_ZZ(l_ts[t].a[1]) << 32) + to_ZZ(l_ts[t].a[0]);
+	ZZ bres = (to_ZZ(l_ts[t].b[2]) << 64) + (to_ZZ(l_ts[t].b[1]) << 32) + to_ZZ(l_ts[t].b[0]);
 	if (ares != aexp[t] || bres != bexp[t]) {
 	if (ares != aexp[t] || bres != bexp[t]) {
 	    cerr << "ares = " << ares << "\n";
 	    cerr << "ares = " << ares << "\n";
 	    cerr << "aexp = " << aexp[t] << "\n";
 	    cerr << "aexp = " << aexp[t] << "\n";
@@ -558,6 +558,78 @@ cout << i << ": " << l_Z[i] << " != " << l_z[i + t * WORDS] << "\n";
 }
 }
 
 
 #ifdef TEST_CUDA
 #ifdef TEST_CUDA
+
+string output_prefix("test_cuda");
+
+typedef map<std::string, pair<ZZ,ZZ> > DTable;
+
+struct CBData {
+    const ZZ_p &base;
+    const ZZ_p &target;
+    const ZZ &order;
+    unsigned long long numdp;
+    DTable dtable;
+    bool found_collision;
+    ZZ expon;
+
+    CBData(const ZZ_p &_base, const ZZ_p &_target, const ZZ &_order) :
+	base(_base), target(_target), order(_order), numdp(0),
+	found_collision(false) {}
+};
+
+// 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
+// dp points to an array of WORDS+7 unsigned ints:
+// - 1 word of threadID/blockID
+// - WORDS words of the dp value
+// - 3 words of a
+// - 3 words of b
+bool dpcallback(void *cbdata, unsigned int *dpwords)
+{
+    CBData *d = (CBData*)cbdata;
+    // WARNING: this assumes
+    //    sizeof(unsigned long) == sizeof(unsigned long long) !
+    ZZ zz_a = to_ZZ(dpwords[WORDS+3]);
+    zz_a <<= 32;
+    zz_a += dpwords[WORDS+2];
+    zz_a <<= 32;
+    zz_a += dpwords[WORDS+1];
+    ZZ zz_b = to_ZZ(dpwords[WORDS+6]);
+    zz_b <<= 32;
+    zz_b += dpwords[WORDS+5];
+    zz_b <<= 32;
+    zz_b += dpwords[WORDS+4];
+
+    // ZZ_p dp = power(d->base, zz_a) * power(d->target, zz_b);
+    // cerr << zz_a << " " << zz_b << " " << dp << "\n";
+
+    // cerr << "DP " << ++(d->numdp) << "\r";
+    pair<ZZ,ZZ> ab(zz_a,zz_b);
+    pair<DTable::iterator, bool> res;
+    string x((const char *)(dpwords+1), WORDS*sizeof(unsigned int));
+
+    res = d->dtable.insert(DTable::value_type(x, ab));
+    if (!res.second) {
+	// Collision!
+	ZZ adiff = to_ZZ(res.first->second.first) - zz_a;
+	ZZ bdiff = zz_b - to_ZZ(res.first->second.second);
+	if (bdiff < 0) bdiff += d->order;
+	ZZ binv;
+	if (InvModStatus(binv, bdiff, d->order) == 0) {
+	    d->expon = MulMod(binv, adiff, d->order);
+	    d->found_collision = true;
+	} else {
+	    if (d->order > (1<<20)) {
+		cerr << "Unhelpful collision\n";
+	    }
+	}
+    }
+
+    return d->found_collision;
+}
+
 int main(int argc, char** argv)
 int main(int argc, char** argv)
 {
 {
 #ifdef DERANDOMIZE
 #ifdef DERANDOMIZE
@@ -597,9 +669,10 @@ int main(int argc, char** argv)
 
 
 	// Try to find the DL_g of y
 	// Try to find the DL_g of y
 	cerr << "DL_" << g << "(" << y << ") mod " << p << "\n";
 	cerr << "DL_" << g << "(" << y << ") mod " << p << "\n";
-	ZZ e = cuda_dl(g, y, pfvec[f], p);
-	cerr << "e = " << e << "\n";
-	cerr << ( (power(g,e) == y) ? "CORRECT!" : "INCORRECT!" ) << "\n";
+	CBData cbdata(g, y, pfvec[f]);
+	cuda_dl(g, y, pfvec[f], p, 4294967, &cbdata);
+	cerr << "e = " << cbdata.expon << "\n";
+	cerr << ( (power(g,cbdata.expon) == y) ? "CORRECT!" : "INCORRECT!" ) << "\n";
     }
     }
 
 
     return 0;
     return 0;