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