parrhoasm.cu 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /*
  2. * cudadl version 0.9: Compute discrete logs in smooth group orders
  3. * using CUDA
  4. * Copyright (C) 2012 by Ryan Henry and Ian Goldberg
  5. * {rhenry,iang}@cs.uwaterloo.ca
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of version 3 of the GNU General Public License as
  9. * published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "cudadl.h"
  20. #include <fstream>
  21. #include <NTL/vec_ZZ.h>
  22. #include <string.h>
  23. #include <limits.h>
  24. #include <sys/time.h>
  25. #include <time.h>
  26. #include <string>
  27. #include <sstream>
  28. #include <utility>
  29. #include <map>
  30. #include "worker.h"
  31. // #define CHECK_RESULTS
  32. // #define VERBOSE
  33. // #include "cuPrintf.cu"
  34. #define BITS_PER_WORD (8 * sizeof(unsigned int))
  35. #define TWO_32_DIV_3 1431655765U // floor( 2^32 / 3 )
  36. #define TWO_32_DIV_3_X2 2863311530U // 2 * floor( 2^32 / 3 )
  37. #define TWO_64_DIV_3 6148914691236517205UL // floor( 2^64 / 3 )
  38. #define SIZE_G WORDS
  39. #define SIZE_Y WORDS
  40. #define SIZE_X (WORDS + 1)
  41. __device__ __constant__ unsigned int c_rho[WORDS + 1], c_r_inv[WORDS + 1], c_rho_prime;
  42. __device__ __constant__ unsigned int c_y[SIZE_Y], c_g[SIZE_G];
  43. #include "cios.asm"
  44. #include "dpstream.cu"
  45. // #define X(idx) x[idx<<5]
  46. // #define Y(idx) (multtype == 0 ? c_g[idx] : multtype == 1 ? c_y[idx] : x[idx<<5])
  47. // #define Y(idx) ((c_g[idx]&typemask0) | (c_y[idx]&typemask1) | (x[idx<<5]&typemask2))
  48. // #define Z(idx) z[idx<<5]
  49. NTL_CLIENT
  50. int cuda_init(int deviceid)
  51. {
  52. cudaError_t cudares = cudaSetDevice(deviceid);
  53. if (cudares != cudaSuccess) {
  54. return -1;
  55. }
  56. return 0;
  57. }
  58. #ifdef CHECK_RESULTS
  59. static void dump(const char *prefix, const unsigned int *di, size_t words)
  60. {
  61. size_t l = words * 4;
  62. const unsigned char *d = (const unsigned char *) di;
  63. d += l;
  64. printf("%s=", prefix);
  65. while(l)
  66. {
  67. --d;
  68. printf("%02X", *d);
  69. --l;
  70. }
  71. printf("\n");
  72. }
  73. #endif
  74. static void checkCUDAError(const char *msg)
  75. {
  76. cudaError_t err = cudaGetLastError();
  77. if (cudaSuccess != err)
  78. {
  79. fprintf(stderr, "Cuda error: %s: %s.\n", msg, cudaGetErrorString(err));
  80. exit(EXIT_FAILURE);
  81. }
  82. }
  83. typedef struct
  84. {
  85. unsigned int x[SIZE_X];
  86. unsigned int a[3], b[3];
  87. } GlobalThreadState;
  88. /*
  89. __device__ unsigned int getgy(int i)
  90. {
  91. return c_rho[i] + c_y[i] + c_g[i];
  92. }
  93. */
  94. #if 0
  95. __device__ void _sub(unsigned int *x)
  96. // x <- x - y
  97. {
  98. asm("sub.cc.u32 %0, %1, %2;" : "=r"(X(0)) : "r"(X(0)), "r"(c_rho[0]));
  99. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(1)) : "r"(X(1)), "r"(c_rho[1]));
  100. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(2)) : "r"(X(2)), "r"(c_rho[2]));
  101. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(3)) : "r"(X(3)), "r"(c_rho[3]));
  102. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(4)) : "r"(X(4)), "r"(c_rho[4]));
  103. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(5)) : "r"(X(5)), "r"(c_rho[5]));
  104. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(6)) : "r"(X(6)), "r"(c_rho[6]));
  105. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(7)) : "r"(X(7)), "r"(c_rho[7]));
  106. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(8)) : "r"(X(8)), "r"(c_rho[8]));
  107. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(9)) : "r"(X(9)), "r"(c_rho[9]));
  108. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(10)) : "r"(X(10)), "r"(c_rho[10]));
  109. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(11)) : "r"(X(11)), "r"(c_rho[11]));
  110. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(12)) : "r"(X(12)), "r"(c_rho[12]));
  111. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(13)) : "r"(X(13)), "r"(c_rho[13]));
  112. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(14)) : "r"(X(14)), "r"(c_rho[14]));
  113. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(15)) : "r"(X(15)), "r"(c_rho[15]));
  114. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(16)) : "r"(X(16)), "r"(c_rho[16]));
  115. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(17)) : "r"(X(17)), "r"(c_rho[17]));
  116. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(18)) : "r"(X(18)), "r"(c_rho[18]));
  117. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(19)) : "r"(X(19)), "r"(c_rho[19]));
  118. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(20)) : "r"(X(20)), "r"(c_rho[20]));
  119. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(21)) : "r"(X(21)), "r"(c_rho[21]));
  120. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(22)) : "r"(X(22)), "r"(c_rho[22]));
  121. asm("subc.cc.u32 %0, %1, %2;" : "=r"(X(23)) : "r"(X(23)), "r"(c_rho[23]));
  122. asm("subc.u32 %0, %1, %2;" : "=r"(X(24)) : "r"(X(24)), "r"(c_rho[24]));
  123. }
  124. __device__ inline bool _gt(const unsigned int * x)
  125. // returns true iff x > y ; x is of length WORDS+1 and y is of length WORDS
  126. {
  127. if (X(24)) return true;
  128. if (X(23) < c_rho[23]) return false;
  129. if (X(23) > c_rho[23]) return true;
  130. if (X(22) < c_rho[22]) return false;
  131. if (X(22) > c_rho[22]) return true;
  132. if (X(21) < c_rho[21]) return false;
  133. if (X(21) > c_rho[21]) return true;
  134. if (X(20) < c_rho[20]) return false;
  135. if (X(20) > c_rho[20]) return true;
  136. if (X(19) < c_rho[19]) return false;
  137. if (X(19) > c_rho[19]) return true;
  138. if (X(18) < c_rho[18]) return false;
  139. if (X(18) > c_rho[18]) return true;
  140. if (X(17) < c_rho[17]) return false;
  141. if (X(17) > c_rho[17]) return true;
  142. if (X(16) < c_rho[16]) return false;
  143. if (X(16) > c_rho[16]) return true;
  144. if (X(15) < c_rho[15]) return false;
  145. if (X(15) > c_rho[15]) return true;
  146. if (X(14) < c_rho[14]) return false;
  147. if (X(14) > c_rho[14]) return true;
  148. if (X(13) < c_rho[13]) return false;
  149. if (X(13) > c_rho[13]) return true;
  150. if (X(12) < c_rho[12]) return false;
  151. if (X(12) > c_rho[12]) return true;
  152. if (X(11) < c_rho[11]) return false;
  153. if (X(11) > c_rho[11]) return true;
  154. if (X(10) < c_rho[10]) return false;
  155. if (X(10) > c_rho[10]) return true;
  156. if (X(9) < c_rho[9]) return false;
  157. if (X(9) > c_rho[9]) return true;
  158. if (X(8) < c_rho[8]) return false;
  159. if (X(8) > c_rho[8]) return true;
  160. if (X(7) < c_rho[7]) return false;
  161. if (X(7) > c_rho[7]) return true;
  162. if (X(6) < c_rho[6]) return false;
  163. if (X(6) > c_rho[6]) return true;
  164. if (X(5) < c_rho[5]) return false;
  165. if (X(5) > c_rho[5]) return true;
  166. if (X(4) < c_rho[4]) return false;
  167. if (X(4) > c_rho[4]) return true;
  168. if (X(3) < c_rho[3]) return false;
  169. if (X(3) > c_rho[3]) return true;
  170. if (X(2) < c_rho[2]) return false;
  171. if (X(2) > c_rho[2]) return true;
  172. if (X(1) < c_rho[1]) return false;
  173. if (X(1) > c_rho[1]) return true;
  174. return (X(0) > c_rho[0]);
  175. }
  176. #endif
  177. #define nmult 1000
  178. #define nlaunch 2
  179. #define threadDimx 32
  180. __global__ void cudaMulmod(GlobalThreadState *global_ts,
  181. unsigned int order_0, unsigned int order_1, unsigned int order_2,
  182. unsigned int dpfreq)
  183. // x <- x * y mod rho
  184. {
  185. CIOS_REG_DECLARE;
  186. // extern __shared__ unsigned int sharedmem[];
  187. register int i;
  188. register int tid = threadIdx.x + threadDimx * threadIdx.y;
  189. register int global_tid = tid + blockDim.x * blockDim.y * blockIdx.x;
  190. unsigned int a_0, a_1, a_2;
  191. unsigned int b_0, b_1, b_2;
  192. unsigned int *global_x_base = global_ts[global_tid].x;
  193. unsigned int *global_a_base = global_ts[global_tid].a;
  194. unsigned int *global_b_base = global_ts[global_tid].b;
  195. // unsigned int *shared_table_base = sharedmem;
  196. // unsigned int *shared_x_base = shared_table_base + threadIdx.y * 32 * (SIZE_X) + threadIdx.x;
  197. unsigned int xlow;
  198. // cuPrintf("d_z = %08X%08X%08X\n", global_x_base[2], global_x_base[1], global_x_base[0]);
  199. CIOS_LOADX(global_x_base);
  200. a_2 = global_a_base[2];
  201. a_1 = global_a_base[1];
  202. a_0 = global_a_base[0];
  203. b_2 = global_b_base[2];
  204. b_1 = global_b_base[1];
  205. b_0 = global_b_base[0];
  206. // cuPrintf("s_A = %08X\n", (unsigned int)a);
  207. // cuPrintf("s_B = %08X\n", (unsigned int)b);
  208. // cuPrintf("s_a = %08X%08X\n", global_a_base[1], global_a_base[0]);
  209. // cuPrintf("s_b = %08X%08X\n", global_b_base[1], global_b_base[0]);
  210. for (i = 0; i < nmult; ++i)
  211. {
  212. //memset(ts[tid].z, 0, (WORDS + 2) * sizeof(unsigned int));
  213. //__syncthreads();
  214. //cuPrintf("x = %p %08X%08X%08X\n", ts[tid].x, ts[tid].x[2], ts[tid].x[1], ts[tid].x[0]);
  215. //cuPrintf("y = %p %08X%08X\n", c_y, c_y[1], c_y[0]);
  216. //cuPrintf("z = %p %08X%08X%08X%08X\n", ts[tid].z, ts[tid].z[3], ts[tid].z[2], ts[tid].z[1], ts[tid].z[0]);
  217. int multtype;
  218. asm("mov.u32 %0, $xr0;" : "=r" (xlow));
  219. if (xlow < TWO_32_DIV_3)
  220. {
  221. multtype = 0;
  222. asm("add.cc.u32 %0, %1, %2;" : "=r"(a_0) : "r"(a_0), "r"((unsigned int)1U));
  223. asm("addc.cc.u32 %0, %1, %2;" : "=r"(a_1) : "r"(a_1), "r"((unsigned int)0U));
  224. asm("addc.u32 %0, %1, %2;" : "=r"(a_2) : "r"(a_2), "r"((unsigned int)0U));
  225. // a += 1;
  226. // cuPrintf("inc a\n");
  227. }
  228. else if (xlow < TWO_32_DIV_3_X2)
  229. {
  230. multtype = 1;
  231. asm("add.cc.u32 %0, %1, %2;" : "=r"(b_0) : "r"(b_0), "r"((unsigned int)1U));
  232. asm("addc.cc.u32 %0, %1, %2;" : "=r"(b_1) : "r"(b_1), "r"((unsigned int)0U));
  233. asm("addc.u32 %0, %1, %2;" : "=r"(b_2) : "r"(b_2), "r"((unsigned int)0U));
  234. // b += 1;
  235. // cuPrintf("inc b\n");
  236. }
  237. else
  238. {
  239. multtype = 2;
  240. asm("add.cc.u32 %0, %1, %2;" : "=r"(a_0) : "r"(a_0), "r"(a_0));
  241. asm("addc.cc.u32 %0, %1, %2;" : "=r"(a_1) : "r"(a_1), "r"(a_1));
  242. asm("addc.u32 %0, %1, %2;" : "=r"(a_2) : "r"(a_2), "r"(a_2));
  243. asm("add.cc.u32 %0, %1, %2;" : "=r"(b_0) : "r"(b_0), "r"(b_0));
  244. asm("addc.cc.u32 %0, %1, %2;" : "=r"(b_1) : "r"(b_1), "r"(b_1));
  245. asm("addc.u32 %0, %1, %2;" : "=r"(b_2) : "r"(b_2), "r"(b_2));
  246. // a += a;
  247. // b += b;
  248. // cuPrintf("double\n");
  249. }
  250. if (a_2 > order_2 || ((a_2 == order_2) && (a_1 > order_1)) || (((a_2 == order_2) && (a_1 == order_1) && (a_0 > order_0)))) {
  251. asm("sub.cc.u32 %0, %1, %2;" : "=r"(a_0) : "r"(a_0), "r"(order_0));
  252. asm("subc.cc.u32 %0, %1, %2;" : "=r"(a_1) : "r"(a_1), "r"(order_1));
  253. asm("subc.u32 %0, %1, %2;" : "=r"(a_2) : "r"(a_2), "r"(order_2));
  254. }
  255. if (b_2 > order_2 || ((b_2 == order_2) && (b_1 > order_1)) || (((b_2 == order_2) && (b_1 == order_1) && (b_0 > order_0)))) {
  256. asm("sub.cc.u32 %0, %1, %2;" : "=r"(b_0) : "r"(b_0), "r"(order_0));
  257. asm("subc.cc.u32 %0, %1, %2;" : "=r"(b_1) : "r"(b_1), "r"(order_1));
  258. asm("subc.u32 %0, %1, %2;" : "=r"(b_2) : "r"(b_2), "r"(order_2));
  259. }
  260. CIOS_MODMUL(multtype);
  261. //memcpy(ts[tid].x, ts[tid].z, (WORDS + 1) * sizeof(unsigned int));
  262. /*
  263. if (_gt(shared_x_base)) {
  264. _sub(shared_x_base);
  265. }
  266. */
  267. //cuPrintf("y = %p %08X%08X\n", c_y, c_y[1], c_y[0]);
  268. //cuPrintf("z = %p %08X%08X\n", ts[tid].x, ts[tid].x[1], ts[tid].x[0]);
  269. //cuPrintf("y = %p %08X%08X\n", c_y, c_y[1], c_y[0]);
  270. // Check for a distinguished point
  271. asm("mov.u32 %0, $xr0;" : "=r" (xlow));
  272. if (xlow <= dpfreq) {
  273. unsigned int *ourbuffer = DPstreamAlloc();
  274. if (ourbuffer) {
  275. CIOS_WRITE_DP(ourbuffer, a_0, a_1, a_2, b_0, b_1, b_2);
  276. }
  277. }
  278. }
  279. CIOS_SAVEX(global_x_base);
  280. global_a_base[0] = a_0;
  281. global_a_base[1] = a_1;
  282. global_a_base[2] = a_2;
  283. global_b_base[0] = b_0;
  284. global_b_base[1] = b_1;
  285. global_b_base[2] = b_2;
  286. // cuPrintf("d_z = %08X%08X%08X\n", global_x_base[2], global_x_base[1], global_x_base[0]);
  287. // cuPrintf("d_A = %08X\n", (unsigned int)a);
  288. // cuPrintf("d_B = %08X\n", (unsigned int)b);
  289. // cuPrintf("d_a = %08X%08X\n", global_a_base[1], global_a_base[0]);
  290. // cuPrintf("d_b = %08X%08X\n", global_b_base[1], global_b_base[0]);
  291. }
  292. int nthreads = 25600;
  293. int nblocks = 50;
  294. void cuda_dl(const ZZ_p &base, const ZZ_p &target, const ZZ &order,
  295. const ZZ &modulus, unsigned int dpfreq, void *cbdata)
  296. {
  297. unsigned long long totmicros = 0;
  298. ZZ_pBak pbak;
  299. pbak.save();
  300. if (NumBits(modulus) <= ((WORDS-1)*BITS_PER_WORD) ||
  301. NumBits(modulus) > WORDS*BITS_PER_WORD) {
  302. cerr << "modulus is not " << WORDS << " words long.\n";
  303. exit(1);
  304. }
  305. long orderbits = NumBits(order);
  306. if (orderbits > 92) {
  307. cerr << "order is larger than 92 bits.\n";
  308. exit(1);
  309. }
  310. unsigned int order_2 = trunc_long(order >> 64, 32);
  311. unsigned int order_1 = trunc_long(order >> 32, 32);
  312. unsigned int order_0 = trunc_long(order, 32);
  313. /*
  314. cerr << "order = " << order << "\n";
  315. cerr << "orderll = " << orderll << "\n";
  316. */
  317. unsigned int *rho, rho_prime, *r, *r_inv;
  318. unsigned int l_y[SIZE_Y], l_g[SIZE_G];
  319. //cout << "rho = " << zz_rho << "\n";
  320. ZZ zz_r = (to_ZZ(1) << (WORDS * BITS_PER_WORD));
  321. ZZ_p::init(zz_r);
  322. ZZ_p zz_p_rho_prime = -to_ZZ_p(1) / to_ZZ_p(modulus);
  323. //cout << "rho_prime = " << zz_p_rho_prime << "\n";
  324. ZZ_p::init(modulus);
  325. ZZ_p zz_p_r, zz_p_r_inv;
  326. zz_p_r = to_ZZ_p(zz_r);
  327. zz_p_r_inv = to_ZZ_p(1) / zz_p_r;
  328. //cout << "r = " << zz_r << "\n";
  329. //cout << "r mod rho = " << rep(zz_p_r) << "\n";
  330. //cout << "r_inv = " << rep(zz_p_r_inv) << "\n";
  331. //cout << "r * r_inv = " << zz_p_r * zz_p_r_inv << "\n";
  332. //cout << "r * r_inv - rho * rho_prime = " << zz_r * rep(zz_p_r_inv) - zz_rho * rep(zz_p_rho_prime) << "\n";
  333. rho = (unsigned int*) calloc((WORDS + 1), sizeof(unsigned int));
  334. r = (unsigned int*) calloc((WORDS + 1), sizeof(unsigned int));
  335. r_inv = (unsigned int*) calloc((WORDS + 1), sizeof(unsigned int));
  336. BytesFromZZ((unsigned char *) rho, modulus, WORDS * sizeof(unsigned int));
  337. BytesFromZZ((unsigned char *) &rho_prime, rep(zz_p_rho_prime), sizeof(unsigned int));
  338. BytesFromZZ((unsigned char *) r, rep(zz_p_r), (WORDS + 1) * sizeof(unsigned int));
  339. BytesFromZZ((unsigned char *) r_inv, rep(zz_p_r_inv), (WORDS + 1) * sizeof(unsigned int));
  340. cudaMemcpyToSymbol(c_rho, rho, (WORDS + 1) * sizeof(unsigned int), 0, cudaMemcpyHostToDevice);
  341. cudaMemcpyToSymbol(c_rho_prime, &rho_prime, sizeof(unsigned int), 0, cudaMemcpyHostToDevice);
  342. cudaMemcpyToSymbol(c_r_inv, r_inv, (WORDS + 1) * sizeof(unsigned int), 0, cudaMemcpyHostToDevice);
  343. checkCUDAError("memcpytosymbol");
  344. /*
  345. if (nthreads % threadDimx) {
  346. nthreads /= threadDimx;
  347. nthreads *= threadDimx;
  348. cerr << "Truncating to " << nthreads << " threads.\n";
  349. }
  350. */
  351. if (nthreads % nblocks) {
  352. cerr << "Error: " << nthreads << " not a multiple of " << nblocks << "\n";
  353. exit(1);
  354. }
  355. const int threadsPerBlock = nthreads / nblocks;
  356. GlobalThreadState *d_ts;
  357. cudaMalloc((void **) &d_ts, nthreads * sizeof(GlobalThreadState));
  358. GlobalThreadState *l_ts;
  359. l_ts = (GlobalThreadState *) calloc(nthreads, sizeof(GlobalThreadState));
  360. unsigned int *l_z;
  361. l_z = (unsigned int *) calloc(nthreads, WORDS * sizeof(unsigned int));
  362. //cudaPrintfInit((1<<20)*16);
  363. DPstreamInit(1<<16);
  364. struct timeval st, et;
  365. memset(l_ts, 0, nthreads * sizeof(GlobalThreadState));
  366. memset(l_z, 0, WORDS * sizeof(unsigned int));
  367. //cout << "y = " << rep(zz_p_y) << "\n";
  368. ZZ_p zz_p_yr = target * zz_p_r;
  369. //cout << "y = " << rep(zz_p_y) << "\n";
  370. ZZ_p zz_p_gr = base * zz_p_r;
  371. BytesFromZZ((unsigned char *) l_y, rep(zz_p_yr), WORDS * sizeof(unsigned int));
  372. BytesFromZZ((unsigned char *) l_g, rep(zz_p_gr), WORDS * sizeof(unsigned int));
  373. cudaMemcpyToSymbol(c_y, l_y, (WORDS) * sizeof(unsigned int), 0, cudaMemcpyHostToDevice);
  374. cudaMemcpyToSymbol(c_g, l_g, (WORDS) * sizeof(unsigned int), 0, cudaMemcpyHostToDevice);
  375. //dump("y", l_y, WORDS);
  376. #ifdef CHECK_RESULTS
  377. int totmult = 0;
  378. bool fail = false;
  379. vec_ZZ aexp, bexp; // The expected values of a and b at completion
  380. aexp.SetLength(nthreads);
  381. bexp.SetLength(nthreads);
  382. #endif
  383. ZZ a = RandomBits_ZZ(orderbits-1);
  384. ZZ b = RandomBits_ZZ(orderbits-1);
  385. ZZ astep = RandomBits_ZZ(orderbits-1);
  386. ZZ bstep = RandomBits_ZZ(orderbits-1);
  387. ZZ_p zz_p_x = power(base, a) * power(target, b);
  388. ZZ_p zz_p_step = power(base, astep) * power(target, bstep);
  389. ZZ_p zz_p_xr = zz_p_x * zz_p_r;
  390. for (int t=0; t<nthreads; ++t)
  391. {
  392. zz_p_xr *= zz_p_step;
  393. a += astep;
  394. a %= order;
  395. b += bstep;
  396. b %= order;
  397. BytesFromZZ((unsigned char *) l_ts[t].x, rep(zz_p_xr), WORDS * sizeof(unsigned int));
  398. // dump("l_x", l_ts[t].x, WORDS);
  399. BytesFromZZ((unsigned char *) l_ts[t].a, a, 3 * sizeof(unsigned int));
  400. BytesFromZZ((unsigned char *) l_ts[t].b, b, 3 * sizeof(unsigned int));
  401. //dump("x", l_ts[t].x, WORDS);
  402. //cout << "x = " << rep(zz_p_x) << "\n";
  403. //cout << "xr = " << rep(zz_p_xr) << "\n";
  404. //dump("rho", rho, WORDS);
  405. #ifdef CHECK_RESULTS
  406. for (int l = 0; l < nmult * nlaunch; ++l)
  407. {
  408. unsigned int w = trunc_long(rep(zz_p_xr), 32);
  409. if (w < TWO_32_DIV_3) {
  410. zz_p_xr *= base;
  411. a++;
  412. } else if (w < TWO_32_DIV_3_X2) {
  413. zz_p_xr *= target;
  414. b++;
  415. } else {
  416. zz_p_xr *= zz_p_xr * zz_p_r_inv;
  417. a += a;
  418. b += b;
  419. }
  420. if (a > order) a -= order;
  421. if (b > order) b -= order;
  422. ++totmult;
  423. }
  424. BytesFromZZ((unsigned char *) (l_z + t * WORDS), rep(zz_p_xr), WORDS * sizeof(unsigned int));
  425. aexp[t] = a;
  426. bexp[t] = b;
  427. #endif
  428. //cout << "zr = " << rep(zz_p_xr) << "\n";
  429. //dump("z", l_z + t * WORDS, WORDS);
  430. }
  431. cudaMemcpy(d_ts, l_ts, nthreads * sizeof(GlobalThreadState), cudaMemcpyHostToDevice);
  432. dim3 tpb(threadDimx, threadsPerBlock/threadDimx);
  433. gettimeofday(&st, NULL);
  434. int launchcount = 0;
  435. #ifdef CHECK_RESULTS
  436. for (int ln=0; ln<nlaunch; ++ln)
  437. #else
  438. bool stop_computing = false;
  439. while(stop_computing == false)
  440. #endif
  441. {
  442. #ifdef VERBOSE
  443. cerr << getpid() << " Launch " << ++launchcount << "...\n";
  444. #else
  445. ++launchcount;
  446. #endif
  447. cudaMulmod<<< nblocks, nthreads/nblocks /*tpb*/, 0 >>>(d_ts,
  448. order_0, order_1, order_2, dpfreq);
  449. cudaThreadSynchronize();
  450. checkCUDAError("kernel launch");
  451. stop_computing = DPstreamParse(cbdata);
  452. //cudaPrintfExtractDPE(dpcallback, cbdata);
  453. //cudaPrintfDisplay(stdout, true);
  454. #ifdef VERBOSE
  455. cerr << getpid() << "\n";
  456. #endif
  457. }
  458. gettimeofday(&et, NULL);
  459. totmicros = (unsigned long long)(et.tv_sec - st.tv_sec) * 1000000 + (et.tv_usec - st.tv_usec);
  460. #ifdef CHECK_RESULTS
  461. cudaMemcpy(l_ts, d_ts, nthreads * sizeof(GlobalThreadState), cudaMemcpyDeviceToHost);
  462. checkCUDAError("memcpy");
  463. int j = 0;
  464. for (int t = 0; t < nthreads; ++t)
  465. {
  466. unsigned int *l_Z = l_ts[t].x;
  467. for (int i = 0; i < WORDS; i++)
  468. {
  469. if (l_Z[i] != l_z[i + t * WORDS])
  470. {
  471. fail = true;
  472. cout << i << ": " << l_Z[i] << " != " << l_z[i + t * WORDS] << "\n";
  473. }
  474. }
  475. if (fail)
  476. {
  477. dump("d_z", l_Z, WORDS);
  478. dump("l_z", l_z + t * WORDS, WORDS);
  479. }
  480. ZZ ares = (to_ZZ(l_ts[t].a[1]) << 32) + to_ZZ(l_ts[t].a[0]);
  481. ZZ bres = (to_ZZ(l_ts[t].b[1]) << 32) + to_ZZ(l_ts[t].b[0]);
  482. if (ares != aexp[t] || bres != bexp[t]) {
  483. cerr << "ares = " << ares << "\n";
  484. cerr << "aexp = " << aexp[t] << "\n";
  485. cerr << "bres = " << bres << "\n";
  486. cerr << "bexp = " << bexp[t] << "\n";
  487. }
  488. ++j;
  489. }
  490. if (!fail) {
  491. cerr << "Results correct.\n";
  492. }
  493. #endif
  494. char timestamp[20];
  495. sprintf(timestamp, "%d.%06d", et.tv_sec, et.tv_usec);
  496. unsigned long long totnanos = totmicros * 1000;
  497. cout << timestamp << ":" << output_prefix << ": " << totmicros << " us / " << nthreads << " = " << totmicros / nthreads << " us / " << (nmult*launchcount) << " = " << totnanos / ((unsigned long long)nthreads * nmult * launchcount) << " ns\n";
  498. cout.flush();
  499. //cudaPrintfEnd();
  500. DPstreamEnd();
  501. cudaFree(d_ts);
  502. free(rho);
  503. free(r_inv);
  504. free(r);
  505. free(l_ts);
  506. free(l_z);
  507. pbak.restore();
  508. }
  509. #ifdef TEST_CUDA
  510. int main(int argc, char** argv)
  511. {
  512. #ifdef DERANDOMIZE
  513. SetSeed(to_ZZ(1));
  514. #else
  515. // Initialize the prng with some randomness from the kernel
  516. unsigned char randbuf[1024];
  517. ifstream urand("/dev/urandom");
  518. urand.read((char *) randbuf, sizeof(randbuf));
  519. urand.close();
  520. ZZ randzz = ZZFromBytes(randbuf, sizeof(randbuf));
  521. SetSeed(randzz);
  522. #endif
  523. ZZ rho, p, q;
  524. vec_ZZ pfvec, qfvec;
  525. cin >> rho >> p >> pfvec >> q >> qfvec;
  526. if (argc > 1) nthreads = atoi(argv[1]);
  527. if (argc > 2) nblocks = atoi(argv[2]);
  528. ZZ_p::init(p);
  529. for (int iter = 0; iter < 1; ++iter) {
  530. // Create the subproblem for the f'th factor of p-1
  531. int f = iter;
  532. ZZ remorder = (p-1)/pfvec[f];
  533. ZZ_p g = power(to_ZZ_p(2), remorder);
  534. ZZ_p y = power(random_ZZ_p(), remorder);
  535. // g should now be of order pfvec[0]. Check that.
  536. if (g == 1 || power(g, pfvec[f]) != 1) {
  537. cerr << "base has the wrong order!\n";
  538. exit(1);
  539. }
  540. // Try to find the DL_g of y
  541. cerr << "DL_" << g << "(" << y << ") mod " << p << "\n";
  542. ZZ e = cuda_dl(g, y, pfvec[f], p);
  543. cerr << "e = " << e << "\n";
  544. cerr << ( (power(g,e) == y) ? "CORRECT!" : "INCORRECT!" ) << "\n";
  545. }
  546. return 0;
  547. }
  548. #endif