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