Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/mty-makai/mty.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 262 - (show annotations) (download) (as text)
Sat Jul 2 05:36:54 2011 UTC (12 years, 9 months ago) by notanpe
File MIME type: text/x-csrc
File size: 22594 byte(s)
魔キー対応
1 /***********************************************************************
2 *
3 * file: mty.c
4 *
5 * まあ、待て屋。
6 *
7 * $Id$
8 *
9 */
10
11 #include <assert.h>
12 #include <stddef.h>
13 #include <stdio.h>
14 #include <time.h>
15 #include <sys/timeb.h>
16
17 #if defined(WIN32)
18
19 #include <windows.h>
20 #include <process.h>
21
22 #elif defined(__GNUC__)
23
24 #include <sys/time.h>
25
26 #endif
27
28 #include "desconst.h"
29 #include "expr_parse.h"
30 #include "hit.h"
31 #include "key.h"
32 #include "log.h"
33 #include "scoreboard.h"
34 #include "synth.h"
35 #include "util.h"
36
37 #ifdef WIN32
38 /* 優先度 */
39 #define PRIO_MIN 0
40 #define PRIO_NORM 0
41 #define PRIO_BELO 1
42 #define PRIO_IDLE 2
43 #define PRIO_MAX 2
44 #define PRIO_DEF 2
45 #endif /* WIN32 */
46
47 /* スレッド数と CPU 数 */
48 #define THREAD_MIN 1
49 #define THREAD_MAX 32
50 int availCPU; /* usage() で使うので大域変数 */
51
52 #define STS_SPAN 5000 /* 速度表示の間隔 (ミリ秒) */
53
54 /* がんばりぐあい */
55 #define GEAR_MAX 10
56 #define GEAR_MIN 1
57 #define GEAR_DEF 10
58 #define GEAR_SLEEP 10
59 #define YOUSUMI 6 /* STS_PAN * YOUSUMI 秒様子見 */
60 int lCntMax;
61
62 /* 塩固定 */
63 char fixedSalt[3]; /* log_print で使うので大域変数 */
64 #define NUMSC 64 /* 塩の文字種数 */
65 static char saltChar[NUMSC] = "abcdefghijklmnopqrstuvwxyz"
66 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
67 "0123456789./";
68
69 static HANDLE mutex_key;
70
71 /* CRYPT64 記述子 */
72 static
73 struct CRYPT64_DESC const *const crypt64_descs[] =
74 {
75 &crypt64_desc,
76 };
77
78 /* 速度評価用 */
79 static int n_cpus;
80 static uint64_t loop_cpu[1024];
81
82 #define USEC_SEC 1000 /* 1秒 */
83
84 static
85 uint64_t
86 usec(void)
87 {
88 uint32_t sec, msec;
89
90 #if !defined(WIN32)
91 struct timeval tv;
92 gettimeofday(&tv, NULL);
93 sec = tv.tv_sec;
94 msec = tv.tv_usec / (1000000 / USEC_SEC);
95 #else
96 struct timeb tm;
97 ftime(&tm);
98 sec = tm.time;
99 msec = tm.millitm / (1000 / USEC_SEC);
100 #endif
101
102 return (uint64_t)USEC_SEC * sec + msec;
103 }
104
105 /***************************************************************
106 *
107 * CPU capabilities を取得
108 * [XXX] あまりにも古いプロセッサのことは考えない。
109 *
110 * a[4] = {EAX,EBX,ECX,EDX}
111 *
112 */
113
114 #if defined(__GNUC__)
115
116 #define cpuid(n,a,b,c,d) \
117 asm("cpuid" \
118 : "=a"(a), "=b"(b), "=c"(c), "=d"(d) \
119 : "a"(n))
120
121 #elif defined(WIN32)
122
123 #define cpuid(n,a,b,c,d) \
124 do {int r[4]; __cpuid(r,n); \
125 (a) = r[0]; (b) = r[1]; (c) = r[2]; (d) = r[3];} while (0)
126
127 #endif
128
129 static
130 unsigned
131 cpuid_getfflags(void)
132 {
133 unsigned a, b, c, d;
134 cpuid(1, a, b, c, d);
135 return d;
136 }
137
138 static
139 int
140 cpuid_issupported(void)
141 {
142 unsigned m = REQUIRED_CAPS;
143 return !((cpuid_getfflags() ^ m) & m);
144 }
145
146 /***************************************************************
147 *
148 * バッチ処理用パケット
149 *
150 */
151
152 static
153 struct PACKET_CRYPT64 *
154 packet_create(int n, /* パケット数 */
155 int tn, /* 末尾要素にて必要なワーク数 */
156 uint8_t const *ini_key)
157 {
158 int i;
159 int siz;
160 void *p;
161 intptr_t a = 128;
162 struct PACKET_CRYPT64 *pkts;
163 assert(IS_POWER2(sizeof(struct PACKET_CRYPT64)));
164 assert(n >= 1);
165
166 siz = (a - 1
167 + (n - 1) * sizeof(struct PACKET_CRYPT64)
168 + offsetof(struct PACKET_CRYPT64, param64.hit[tn]));
169 p = calloc(siz, 1);
170 /* バンダリあわせ */
171 pkts = (struct PACKET_CRYPT64 *)(((intptr_t)p
172 + a - 1)
173 & -a);
174 #if DEBUG>=1
175 fprintf(stderr,
176 "packet(n=%d,tn=%d) %d allocated; %p aligned to %p\n",
177 n, tn,
178 siz, p, pkts);
179 #endif
180
181 /* 内部の初期化
182 コピーして回るのは、厳密には
183 最終要素のケツを破ってしまうことになるので
184 どうせ速度も要求されないしベタコード */
185 for (i = 0; i < n; i++)
186 {
187 int j, k;
188
189 /* t[16] は、内部演算で使用する、all 1 が入っている */
190 memset(&pkts[i].param64.t[T_INV], -1, sizeof(SLICE));
191
192 /* 固定キーの生成 */
193 key_init_sk(&pkts[i].key64);
194
195 /* キースケジュールをここに押し込めておく
196 従来は crypt64.S 内で完結するように引いていた */
197 for (j = 0; j < 28; j++)
198 for (k = 0; k < N_ALU; k++)
199 pkts[i].key64.ks[j].a[k] = sizeof(WS_T) * ks_ls[j];
200
201 /* 念のため、鍵をここで落ち着けておく(不要?) */
202 for (j = 0; j < 8; j++)
203 key_set64(&pkts[i].key64, j, pkts[i].uk.key[j] = ini_key[j], 0, 0x7F);
204 }
205
206 return pkts;
207 }
208
209 /***************************************************************
210 *
211 * thread
212 *
213 */
214
215 #if defined(__GNUC__)
216
217 typedef int32_t ATOMWORD_T;
218
219 #define LOCK_INC(p) \
220 asm volatile ("lock incl %0" \
221 : "=m"(*(p)) \
222 : /*nil*/ \
223 : "memory")
224
225 #define LOCK_DEC(p) \
226 asm volatile ("lock decl %0" \
227 : "=m"(*(p)) \
228 : /*nil*/ \
229 : "memory")
230
231 #define LOCK_CAS(pd,s,r) \
232 ({ ATOMWORD_T a; \
233 asm volatile ("lock cmpxchg %2,%1" \
234 : "=a"(a) \
235 : "m"(*(pd)), "r"(s), "0"(r) \
236 : "memory");a;})
237
238 #define LOCK_CASP(pd,s,r) \
239 ({ void *a; \
240 asm volatile ("lock cmpxchg %2,%1" \
241 : "=a"(a) \
242 : "m"(*(pd)), "r"(s), "0"(r) \
243 : "memory");a;})
244
245 #elif defined(WIN32)
246
247 typedef LONG ATOMWORD_T;
248
249 #define LOCK_INC(p) InterlockedIncrement((LONG *)(p))
250 #define LOCK_DEC(p) InterlockedDecrement((LONG *)(p))
251 #define LOCK_CAS(pd,s,r) InterlockedCompareExchange((LONG *)(pd), s, r)
252 #define LOCK_CASP(pd,s,r) InterlockedCompareExchangePointer((PVOID *)(pd), (PVOID)(s), (PVOID)r)
253
254 #else
255 #error "configuration not implemented"
256 #endif
257
258 #if defined(WIN32)
259
260 typedef DWORD THREAD_TIMEOUT_T;
261
262 #define THREAD_INFINITE INFINITE
263
264 typedef HANDLE THREAD_TH_T;
265
266 #define thread_sleep(n) Sleep(n)
267 #define thread_create(th, proc, arg) {(th) = (HANDLE)_beginthread(proc, 8192, arg);}
268 #define thread_get_tid() GetCurrentThread()
269 #define thread_set_priority(tid,n) SetThreadPriority(tid, n)
270 #define thread_set_affinity(tid,m) SetThreadAffinityMask(tid, (DWORD_PTR)1 << (m))
271
272 #elif defined(_POSIX_SOURCE)
273
274 #include <pthread.h>
275 #include <unistd.h>
276
277 typedef int THREAD_TIMEOUT_T;
278
279 #define THREAD_INFINITE INT_MAX
280
281 #if defined(THREAD_PRIORITY_BELOW_NOROMAL) || defined(THREAD_PRIORITY_IDLE)
282 #error "unsupported implementation"
283 #endif
284
285 #define THREAD_PRIORITY_NORMAL 14
286 #define THREAD_PRIORITY_BELOW_NORMAL 15
287 #define THREAD_PRIORITY_IDLE 16
288
289 typedef pthread_t THREAD_TH_T;
290
291 #define thread_sleep(n) (usleep(1000 * (n)) != EINVAL || sleep((n) / 1000))
292 #define thread_create(th, proc, arg) thread_create_p(&(th), proc, arg)
293
294 static
295 void
296 thread_create_p(pthread_t *th, NORETURN (*proc)(void *), void *param)
297 {
298 pthread_create(th, NULL, (void *(*)(void *))proc, param);
299 }
300
301 #if defined(__linux__)
302
303 /* デフォルトスケジューリングポリシーでは
304 優先度設定したりアイドルスレッド起こしても
305 おもしろくないので、そのへんは今後の研究課題。 */
306
307 #include <linux/unistd.h>
308 #ifdef _syscall0
309 _syscall0(pid_t,gettid)
310 #define thread_get_tid() gettid()
311 #else /* _syscall0 */
312 #include <sys/syscall.h>
313 #define thread_get_tid() (pid_t)syscall(SYS_gettid)
314 #endif /* _syscall0 */
315
316 static
317 int thread_set_affinity(pid_t tid, int i)
318 {
319 cpu_set_t m;
320 CPU_ZERO(&m);
321 CPU_SET(i, &m);
322 return sched_setaffinity(tid, sizeof(m), &m);
323 }
324
325 #else
326
327 /* POSIX では、スレッド単位のスケジューリングに介入できない。 */
328
329 #endif
330
331 #else
332 #error "configuration not supported"
333 #endif
334
335 struct THREAD_PARAM
336 {
337 /* 以下は共通情報のコピー */
338 CODE_T *code;
339 long code_cmp;
340 unsigned seed;
341
342 /* 以下はスレッド固有 */
343 #ifdef thread_set_priority
344 int pri;
345 #endif
346 };
347
348 static
349 uint64_t
350 thread_avail(void)
351 {
352 #if !USE_MT
353
354 return 0x1U;
355
356 #elif defined(WIN32) /* Win32 API */
357 DWORD_PTR mask, mask_s;
358 if (!GetProcessAffinityMask(GetCurrentProcess(),
359 &mask,
360 &mask_s)
361 || !mask
362 || !mask_s)
363 return 0x1U;
364 #if DEBUG>=1
365 fprintf(stderr,
366 "m=%08X s=%08X\n",
367 (unsigned)mask,
368 (unsigned)mask_s);
369 #endif
370 #if 0
371 if (popcnt64(mask_s) == 1)
372 /* 何も言うまい */;
373 else if (mask == mask_s)
374 fprintf(stderr,
375 "通常の%d倍とはよく言ったものです。\n",
376 popcnt64(mask));
377 else
378 fprintf(stderr,
379 "最高速力の%g倍の力でてきとうにがんばるよ。\n",
380 (double)popcnt64(mask) / popcnt64(mask_s));
381 #endif /* 0 */
382 return mask;
383
384 #elif defined(__linux__) /* sched.h 拡張 */
385
386 int i;
387 uint64_t m = 0;
388 cpu_set_t am;
389 if (sched_getaffinity(getpid(), sizeof(am), &am) < 0)
390 return 0x1U;
391
392 for (i = 0; i < 64 && i < CPU_SETSIZE; i++)
393 if (CPU_ISSET(i, &am))
394 m |= 1ULL << i;
395
396 return m;
397 #else
398
399 /* XXX プロセッサ数を調べ上げてください */
400 return 0x01U;
401
402 #endif
403 }
404
405 static
406 NORETURN
407 thread_crypt64_new(void *a_param)
408 {
409 struct THREAD_PARAM *param = a_param;
410 CODE_T *code = param->code;
411 CODE_T *cmp = code + param->code_cmp;
412 struct KS_KEY key;
413 struct PACKET_CRYPT64 *pkt = packet_create(16, 1024, key.key);
414 uint64_t *ploop;
415 THREAD_TH_T th = thread_get_tid();
416 int lc;
417
418 WaitForSingleObject(mutex_key, INFINITE);
419
420 OLDPRINT( "n_cpus %d\n", n_cpus );
421 ploop = &loop_cpu[n_cpus++];
422 lc = 0;
423
424 OLDPRINT( "(unsigned)th %u\n", (unsigned)th );
425 OLDPRINT( "param->seed %u\n", param->seed );
426 /* th はスレッドが違っても同じ値になってる */
427 srand(usec() ^ param->seed ^ (unsigned)th);
428 key_init(&key);
429
430 ReleaseMutex(mutex_key);
431
432 #ifdef thread_set_priority
433 thread_set_priority(th, param->pri);
434 #endif
435
436 if ( fixedSalt[0] != '\0' ) {
437 int ki;
438
439 key.key[1] = fixedSalt[0];
440 key.key[2] = fixedSalt[1];
441 set_salt(code, crypt64_descs[0], key.key);
442 key.key[7] = '\0';
443 key.key[8] = '\0';
444 for ( ;; ) {
445 for ( ki = 0; ki < 4; ki++ ) {
446 key.key[ki] = rand() % 0x7f + 1;
447 key_set64(&pkt->key64, ki, key.key[ki], key.key[ki] ^ pkt->uk.key[ki], 0);
448 pkt->uk.key[ki] = key.key[ki];
449 }
450 for ( key.key[4] = 0x01; key.key[4] <= 0x7f; key.key[4]++ ) {
451 key_set64(&pkt->key64, 4, key.key[4], key.key[4] ^ pkt->uk.key[4], 0);
452 pkt->uk.key[4] = key.key[4];
453 for ( key.key[5] = 0x01; key.key[5] <= 0x7f; key.key[5]++ ) {
454 key_set64(&pkt->key64, 5, key.key[5], key.key[5] ^ pkt->uk.key[5], 0);
455 pkt->uk.key[5] = key.key[5];
456 for ( key.key[6] = 0x01; key.key[6] <= 0x7f; key.key[6]++ ) {
457 key_set64(&pkt->key64, 6, key.key[6], key.key[6] ^ pkt->uk.key[6], 0);
458 pkt->uk.key[6] = key.key[6];
459 CALL_CRYPT64(code, &pkt->key64, &pkt->param64);
460 CALL_CMP64(cmp, pkt->param64.hit, pkt->param64.lr);
461 check_hit(pkt, pkt->param64.hit);
462 (*ploop)++;
463 #ifdef ENABLE_GEAR
464 lc++;
465 if ( lCntMax != 0 ) {
466 if ( lc > lCntMax ) {
467 OLDPRINT( "before %I64u\n", usec() );
468 Sleep( (DWORD)GEAR_SLEEP );
469 OLDPRINT( "after %I64u\n", usec() );
470 lc = 0;
471 }
472 }
473 #endif /* ENABLE_GEAR */
474 }
475 }
476 }
477 }
478 }
479
480 for (;;)
481 {
482 do
483 {
484 int j;
485 for (j = 0; j < 8; j++)
486 {
487 key_set64(&pkt->key64, j, key.key[j], key.key[j] ^ pkt->uk.key[j], 0);
488 pkt->uk.key[j] = key.key[j];
489 }
490 CALL_CRYPT64(code,
491 &pkt->key64,
492 &pkt->param64);
493 CALL_CMP64(cmp,
494 pkt->param64.hit,
495 pkt->param64.lr);
496 check_hit(pkt, pkt->param64.hit);
497 (*ploop)++;
498 #ifdef ENABLE_GEAR
499 lc++;
500 if ( lCntMax != 0 ) {
501 if ( lc > lCntMax ) {
502 OLDPRINT( "before %I64u\n", usec() );
503 Sleep( (DWORD)GEAR_SLEEP );
504 OLDPRINT( "after %I64u\n", usec() );
505 lc = 0;
506 }
507 }
508 #endif /* ENABLE_GEAR */
509 }
510 while (key_inc(&key, 6, 8) || key_inc(&key, KEY_SHUFFLE_POS, 8));
511 OLDPRINT( "saaaaalt chaaaaange\n" );
512
513 WaitForSingleObject(mutex_key, INFINITE);
514 key_reset(&key, 0);
515 ReleaseMutex(mutex_key);
516 }
517
518 /* notreached */
519 }
520
521 char
522 *bname( char *path )
523 {
524 char *p;
525
526 OLDPRINT( "path <%s>\n", path );
527
528 for ( p = path; *p != '\0'; p++ )
529 ;
530 while ( *p != '/' && *p != '\\' && p != path ) {
531 if ( *p == '.' ) {
532 *p = '\0';
533 }
534 p--;
535 }
536 if ( p != path ) {
537 p++;
538 }
539
540 OLDPRINT( "p <%s>\n", p );
541
542 return( p );
543 }
544
545 void
546 usage( path )
547 char *path;
548 {
549 char *myName;
550
551 myName = bname( path );
552 printf( "まあ、待て屋。魔改造版 (%s)\n", KIND );
553 printf( "%s [-h] [-v] [-p num] [-t num|-m mask] [-g num] [-z]\n", myName );
554 printf( " -h : これを表示\n" );
555 printf( " -v : 冗長メッセージ\n" );
556 printf( " -p num : 優先度の設定 ( %d ≦ num ≦ %d, デフォルトは %d )\n",
557 PRIO_MIN, PRIO_MAX, PRIO_DEF );
558 printf( " %d : 通常\n", PRIO_NORM );
559 printf( " %d : 通常以下\n", PRIO_BELO );
560 printf( " %d : 低\n", PRIO_IDLE );
561 printf( " ※ -t と -m は排他 (あとから指定したほうが有効)\n" );
562 printf( " ※ -m で指定できるのは有効な論理 CPU 数分まで\n" );
563 printf( " -t num : 検索スレッド数 ( %d ≦ num ≦ %d, デフォルトは %d )\n",
564 THREAD_MIN, availCPU, availCPU );
565 printf( " -m mask : 実行する CPU を指定するマスク ( 1 ビット ≦ mask のビット数 ≦ %d ビット )\n",
566 THREAD_MAX );
567 printf( " -g num : がんばりぐあい ( %d (やる気なし) ≦ num ≦ %d (フルパワー), デフォルトは、%d )\n", GEAR_MIN, GEAR_MAX, GEAR_DEF );
568 printf( " -z : 全空間モード\n" );
569 }
570
571 /***************************************************************
572 *
573 * メインループとか
574 *
575 */
576
577 int
578 main(int argc, char *argv[])
579 {
580 int i;
581 CODE_T *code = NULL;
582 long code_cmp;
583 FILE *sfp; /* scoreboard */
584 struct ITREE *root_expr;
585 uint64_t proc_mask;
586 int nThread;
587 struct THREAD_PARAM *threads = NULL;
588 int nthreads;
589 int tn;
590 int aveSpeed, spanSpeed, bestSpeed;
591 int gear;
592 int sCnt;
593 int tmplCntMax;
594 int maxSrchCnt;
595 int verbose;
596 DWORD priority;
597
598 /* 鍵文字列 */
599 struct KS_KEY key;
600
601 #define UPDATE_INTERVAL 8 /* 速度表示の間隔 秒 */
602 struct status {
603 uint64_t startTime; /* 開始時刻 ミリ秒 */
604 uint64_t lastTime; /* 最後に表示した時刻 ミリ秒 */
605 uint64_t loop; /* 総検索個数 */
606 uint64_t lastloop; /* 最後に表示した時の loop */
607 } status;
608 uint64_t curTime;
609
610 #ifdef USECTEST
611 {
612 int i;
613 for ( i = 0; i < USECTEST; i++ ) {
614 printf( "%I64u\n", usec() );
615 }
616 }
617 #endif /* USECTEST */
618
619 if (!cpuid_issupported())
620 {
621 fprintf(stderr, "この環境で走らせることが想定されていません。\n");
622 exit(1);
623 }
624
625 {
626 int optChar;
627 extern char *optarg;
628 extern int optind;
629 char *chPtr;
630 uint64_t availMask;
631 uint64_t pmask;
632
633 availMask = thread_avail(); /* 有効なマスク */
634 availCPU = popcnt64( availMask ); /* 有効な CPU 数 */
635
636 priority = PRIO_DEF;
637 nThread = 0;
638 pmask = 0;
639 verbose = 0;
640 gear = GEAR_DEF;
641 fixedSalt[0] = fixedSalt[1] = fixedSalt[2] = '\0';
642
643 /* abcdef ijkl no qrs u wxy 未使用 */
644 /* gh m p t v z 使用済み */
645 while ( (optChar = getopt(argc, argv, "g:hm:p:t:vz")) != EOF ) {
646 switch ( optChar ) {
647 case 'g':
648 #ifdef ENABLE_GEAR
649 gear = atoi( optarg );
650 if ( gear < GEAR_MIN || gear > GEAR_MAX ) {
651 usage( argv[0] );
652 exit( 1 );
653 }
654 #else /* ENABLE_GEAR */
655 printf( "-g オプションは無効化されています\n" );
656 #endif /* ENABLE_GEAR */
657 break;
658 case 'h':
659 usage( argv[0] );
660 exit( 0 );
661 break;
662 case 'm':
663 nThread = 0; /* スレッド数とは排他 */
664 if ( strlen( optarg ) > THREAD_MAX ) {
665 usage( argv[0] );
666 exit( 1 );
667 }
668 for ( chPtr = optarg; *chPtr != '\0'; chPtr++ ) {
669 pmask <<= 1;
670 switch ( *chPtr ) {
671 case '0': /* なにもしない */ break;
672 case '1': pmask |= 1; break;
673 default:
674 usage( argv[0] );
675 exit( 1 );
676 break;
677 }
678 }
679 if ( pmask == 0 ) {
680 usage( argv[0] );
681 exit( 1 );
682 }
683 break;
684 case 'p':
685 priority = atoi( optarg );
686 if ( priority < PRIO_MIN || priority > PRIO_MAX ) {
687 usage( argv[0] );
688 exit( 1 );
689 }
690 break;
691 case 't':
692 pmask = 0; /* マスクとは排他 */
693 nThread = atoi( optarg );
694 if ( nThread < THREAD_MIN || nThread > availCPU ) {
695 usage( argv[0] );
696 exit( 1 );
697 }
698 break;
699 case 'v':
700 verbose = 1;
701 break;
702 case 'z':
703 srand( usec() );
704 fixedSalt[0] = saltChar[rand() % NUMSC];
705 fixedSalt[1] = saltChar[rand() % NUMSC];
706 break;
707 default:
708 usage( argv[0] );
709 exit( 1 );
710 }
711 }
712
713 #ifdef MAKEY
714 fprintf(stderr, "魔キー空間バージョンにつき、シロウトにはおすすめできない。\n\n");
715 #endif /* MAKEY */
716
717 if ( pmask == 0 && nThread == 0 ) {
718 /* 指定がなければ、使える CPU 全部 */
719 proc_mask = availMask;
720 }
721
722 if ( pmask != 0 ) {
723 /* マスクで指定の場合、そのまんま */
724 if ( (availMask & pmask) != pmask ) {
725 printf( "そんな CPU はねぇ!\n" );
726 exit( 1 );
727 }
728 proc_mask = pmask;
729 }
730
731 if ( nThread != 0 ) {
732 /* スレッド数の場合、マスクに変換 */
733 proc_mask = 0; /* 念のため */
734 for ( i = 0; i < THREAD_MAX; i++ ) {
735 if ( availMask & 1ULL<<i ) {
736 if ( nThread > 0 ) {
737 proc_mask |= 1ULL<<i;
738 }
739 nThread--;
740 }
741 }
742 }
743
744 if ( gear != GEAR_MAX ) {
745 /* CPU 使用率が正しく見えるように、秘孔をついてみる */
746 TIMECAPS tc;
747 if ( timeGetDevCaps( &tc, sizeof( TIMECAPS ) ) == MMSYSERR_NOERROR ) {
748 timeBeginPeriod( tc.wPeriodMin );
749 }
750 }
751
752 nThread = popcnt64( proc_mask );
753 printf( "%d 個の検索スレッドを起動\n", nThread );
754 }
755
756 assert((1 << N_STRIDE) == N_ALU * ALU_BITS);
757
758 mutex_key = CreateMutex(NULL, FALSE, NULL);
759
760 #ifdef SPECIAL
761 initSpecial();
762 #endif /* SPECIAL */
763
764 /* タゲ読み込み */
765 root_expr = expr_parse("target.txt");
766
767 if ( verbose ) {
768 int i;
769 printf( "優先度を" );
770 switch ( priority ) {
771 case PRIO_NORM : printf( "通常" ); break;
772 case PRIO_BELO : printf( "通常以下" ); break;
773 case PRIO_IDLE : printf( "低" ); break;
774 }
775 printf( "に設定\n" );
776 printf( "CPU : " );
777 for ( i = 0; i < THREAD_MAX; i++ ) {
778 if ( proc_mask & 1ULL<<i ) {
779 printf( "%d ", i );
780 }
781 }
782 printf( "を使用\n" );
783 if ( gear == GEAR_MAX ) {
784 printf( "CPU を 100%% 使用\n" );
785 } else {
786 printf( "CPU を %d 割ぐらい使用\n", gear );
787 }
788 if ( fixedSalt[0] != '\0' ) {
789 printf( "全空間モード (salt:%c%c)\n", fixedSalt[0], fixedSalt[1] );
790 }
791 #ifdef SPECIAL
792 dispSpecial();
793 #else /* SPECIAL */
794 printf( "特殊検索は無効化されています\n" );
795 #endif /* SPECIAL */
796 }
797
798 #ifdef WIN32
799 /* 【注意】priority を上書きしている */
800 switch ( priority ) {
801 case PRIO_NORM : priority = NORMAL_PRIORITY_CLASS; break;
802 case PRIO_BELO : priority = BELOW_NORMAL_PRIORITY_CLASS; break;
803 case PRIO_IDLE : priority = IDLE_PRIORITY_CLASS; break;
804 }
805 SetPriorityClass( GetCurrentProcess(), priority );
806 #endif
807
808 /* コードを生成・展開
809 起動予定スレッド数に応じて
810 生成するコードを変える */
811 sfp = scoreboard_open();
812 fwrite(crypt64_descs[0]->pro, 1, crypt64_descs[0]->cmp_pro - crypt64_descs[0]->pro, sfp); /* prologue & コアループ */
813
814 #if 0
815 if (0&&proc_mask == 1U)
816 {
817 /* single */
818 code_cmp = 0;
819 }
820 else
821 #endif
822 {
823 /* multi */
824 fwrite(crypt64_descs[0]->ep, 1, crypt64_descs[0]->ep_end - crypt64_descs[0]->ep, sfp); /* epilogue */
825
826 /* 比較器のみを生成(前半) */
827 code_cmp = ftell(sfp);
828 fseek(sfp, (-code_cmp) & 63, SEEK_CUR);
829 code_cmp = ftell(sfp);
830 fwrite(crypt64_descs[0]->pro, 1, crypt64_descs[0]->crypt - crypt64_descs[0]->pro, sfp); /* prologue */
831 }
832
833 /* 比較部を生成 */
834 fwrite(crypt64_descs[0]->cmp_pro, 1, crypt64_descs[0]->cmp_ep - crypt64_descs[0]->cmp_pro, sfp); /* 比較器準備 */
835 tn = synth_synthesize(sfp, root_expr);
836 fwrite(crypt64_descs[0]->cmp_ep, 1, crypt64_descs[0]->ep_end - crypt64_descs[0]->cmp_ep, sfp); /* epilogue */
837
838 /* コードをメモリに貼り付ける */
839 code = scoreboard_map(sfp);
840
841 /* キーの初期化 */
842 WaitForSingleObject(mutex_key, INFINITE);
843 srand(usec());
844 key_init(&key);
845 ReleaseMutex(mutex_key);
846 set_salt(code, crypt64_descs[0], key.key);
847
848 if (log_open("log.txt") != 0) return 1;
849
850 WaitForSingleObject(mutex_key, INFINITE);
851
852 /* 働くおじさんを量産 */
853 nthreads = 0;
854 if (code_cmp)
855 {
856 THREAD_TH_T h;
857 int ots = -1;
858 threads = calloc(2 * popcnt64(proc_mask), sizeof(*threads));
859 for (i = 0; i < 64; i++)
860 if (proc_mask & (1ULL << i))
861 {
862 if (0&&ots < 0)
863 {
864 /* 自分自身のスケジューリング
865 こーゆー系のアプリは低めに設定するのが吉(かも) */
866 #ifdef WIN32
867 h = GetCurrentProcess();
868 SetPriorityClass(h, BELOW_NORMAL_PRIORITY_CLASS);
869 #endif
870 #if defined(thread_set_priority)
871 /* 心の隙間お埋めします */
872 threads[nthreads].code = code;
873 threads[nthreads].code_cmp = code_cmp;
874 threads[nthreads].seed = rand();
875 threads[nthreads].pri = THREAD_PRIORITY_IDLE;
876 thread_create(h, thread_crypt64_new, &threads[nthreads]);
877 nthreads++;
878 #endif
879 if (!code_cmp)
880 break;
881
882 /* 自分自身の残りの設定を、あとでやる */
883 ots = i;
884 }
885 else
886 {
887 /* 他スレッドは、やや低めの優先度で。 */
888 threads[nthreads].code = code;
889 threads[nthreads].code_cmp = code_cmp;
890 threads[nthreads].seed = rand();
891 #ifdef thread_set_priority
892 //threads[nthreads].pri = THREAD_PRIORITY_BELOW_NORMAL;
893 threads[nthreads].pri = THREAD_PRIORITY_LOWEST;
894 #endif
895 thread_create(h, thread_crypt64_new, &threads[nthreads]);
896 #ifdef thread_get_tid
897 thread_set_affinity(h, i);
898 #endif
899 nthreads++;
900 #if 0
901 /* IDLE */
902 threads[nthreads].code = code;
903 threads[nthreads].code_cmp = code_cmp;
904 threads[nthreads].seed = rand();
905 #ifdef thread_set_priority
906 threads[nthreads].pri = THREAD_PRIORITY_IDLE;
907 #endif
908 thread_create(h, thread_crypt64_new, &threads[nthreads]);
909 #ifdef thread_get_tid
910 SetThreadAffinityMask(h, proc_mask);
911 #endif
912 nthreads++;
913 #endif
914 }
915 }
916 #ifdef thread_get_tid
917 if (ots)
918 thread_set_affinity(thread_get_tid(), ots);
919 #endif
920 }
921
922 fprintf(stderr, "検索開始!\n");
923 ReleaseMutex(mutex_key);
924
925 memset( &status, 0, sizeof( struct status ) );
926 status.startTime = status.lastTime = usec();
927
928 bestSpeed = 0;
929 sCnt = 0;
930 lCntMax = 0;
931 maxSrchCnt = 0;
932 for ( ;; ) {
933 uint64_t diffTime;
934 uint64_t spanLoop;
935
936 Sleep(STS_SPAN);
937
938 #ifdef OLDEBUG
939 putchar( '\n' );
940 #endif /* DEBUG */
941 status.loop = 0;
942 for (i = 0; i < n_cpus; i++) {
943 OLDPRINT( "loop_cpu[%d] %d\n", i, loop_cpu[i] );
944 status.loop += loop_cpu[i];
945 }
946 status.loop *= N_ALU * ALU_BITS;
947
948 spanLoop = status.loop - status.lastloop;
949 if ( spanLoop > maxSrchCnt ) {
950 maxSrchCnt = spanLoop;
951 }
952
953 curTime = usec();
954
955 /* 通算 (単位 trips/usec = ktrips/sec) */
956 diffTime = curTime - status.startTime;
957 aveSpeed = status.loop / diffTime;
958
959 /* 区間 (単位 trips/usec = ktrips/sec) */
960 diffTime = curTime - status.lastTime;
961 spanSpeed = spanLoop / diffTime;
962
963 /* 最速 */
964 if ( spanSpeed > bestSpeed ) {
965 bestSpeed = spanSpeed;
966 if ( gear != GEAR_MAX ) {
967 tmplCntMax = ((maxSrchCnt / (N_ALU * ALU_BITS)) * gear / 10) / ((STS_SPAN - (STS_SPAN * gear / 10)) / GEAR_SLEEP) / nThread;
968 }
969 }
970
971 if ( gear != GEAR_MAX ) {
972 if ( sCnt == YOUSUMI && lCntMax == 0 ) {
973 if ( tmplCntMax < 1 ) {
974 lCntMax = 1;
975 } else {
976 lCntMax = tmplCntMax;
977 }
978 OLDPRINT( "lCntMax = %d\n", lCntMax );
979 printf( "\nCPU 使用率制限モード開始\n" );
980 }
981 }
982 sCnt++;
983
984 status.lastTime = curTime;
985 status.lastloop = status.loop;
986
987 fprintf(stderr,
988 "通算 %dktrips/s [区間 %dktrips/s] {最速 %dktrips/s}\r",
989 aveSpeed, spanSpeed, bestSpeed );
990 }
991
992 return 0;
993 }
994
995 /*
996 * Local Variables:
997 * tab-width: 4
998 * End:
999 *
1000 * EOF */

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Rev URL

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26