Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 254 - (hide 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 chapuni 1 /***********************************************************************
2     *
3 chapuni 26 * file: mty.c
4 chapuni 1 *
5 chapuni 2 * まあ、待て屋。
6 chapuni 1 *
7     * $Id$
8     *
9     */
10    
11     #include <assert.h>
12 chapuni 20 #include <stddef.h>
13 chapuni 1 #include <stdio.h>
14     #include <time.h>
15 notanpe 192 #include <sys/timeb.h>
16 chapuni 10
17     #if defined(WIN32)
18    
19     #include <windows.h>
20 notanpe 148 #include <process.h>
21 chapuni 10
22     #elif defined(__GNUC__)
23    
24     #include <sys/time.h>
25    
26     #endif
27    
28 chapuni 41 #include "desconst.h"
29 chapuni 46 #include "expr_parse.h"
30 notanpe 252 #include "hit.h"
31     #include "key.h"
32     #include "log.h"
33 chapuni 46 #include "scoreboard.h"
34     #include "synth.h"
35 notanpe 148 #include "util.h"
36 chapuni 1
37 notanpe 254 #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 notanpe 252 static HANDLE mutex_key;
53 notanpe 198
54 notanpe 192 /* CRYPT64 記述子 */
55     static
56     struct CRYPT64_DESC const *const crypt64_descs[] =
57     {
58     &crypt64_desc,
59     };
60    
61 notanpe 252 /* 速度評価用 */
62     static int n_cpus;
63     static uint64_t loop_cpu[1024];
64 chapuni 1
65 notanpe 192 #define USEC_SEC 1000 /* 1秒 */
66    
67 chapuni 1 static
68 notanpe 192 uint64_t
69 notanpe 148 usec(void)
70 notanpe 119 {
71 notanpe 120 uint32_t sec, msec;
72    
73 notanpe 119 #if !defined(WIN32)
74     struct timeval tv;
75     gettimeofday(&tv, NULL);
76 notanpe 120 sec = tv.tv_sec;
77 notanpe 192 msec = tv.tv_usec / (1000000 / USEC_SEC);
78 notanpe 119 #else
79     struct timeb tm;
80     ftime(&tm);
81 notanpe 120 sec = tm.time;
82 notanpe 192 msec = tm.millitm / (1000 / USEC_SEC);
83 notanpe 119 #endif
84 notanpe 120
85 notanpe 192 return (uint64_t)USEC_SEC * sec + msec;
86 notanpe 119 }
87    
88 chapuni 1 /***************************************************************
89     *
90 notanpe 192 * CPU capabilities を取得
91     * [XXX] あまりにも古いプロセッサのことは考えない。
92 chapuni 1 *
93 notanpe 192 * a[4] = {EAX,EBX,ECX,EDX}
94     *
95 chapuni 1 */
96    
97 notanpe 192 #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 notanpe 148 {
116 notanpe 192 unsigned a, b, c, d;
117     cpuid(1, a, b, c, d);
118     return d;
119     }
120 chapuni 1
121 notanpe 148 static
122 notanpe 192 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 notanpe 148 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 notanpe 192 intptr_t a = 128;
145 notanpe 148 struct PACKET_CRYPT64 *pkts;
146     assert(IS_POWER2(sizeof(struct PACKET_CRYPT64)));
147     assert(n >= 1);
148    
149 notanpe 192 siz = (a - 1
150 notanpe 148 + (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 notanpe 192 + a - 1)
156     & -a);
157 notanpe 148 #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 notanpe 192 int j, k;
171 notanpe 148
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 notanpe 192 for (k = 0; k < N_ALU; k++)
182     pkts[i].key64.ks[j].a[k] = sizeof(WS_T) * ks_ls[j];
183 notanpe 148
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 notanpe 252 #elif defined(_POSIX_SOURCE)
256 notanpe 148
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 notanpe 253 long code_cmp;
319 notanpe 252 unsigned seed;
320 notanpe 148
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 notanpe 254 #if 0
350 notanpe 148 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 notanpe 254 #endif /* 0 */
361 notanpe 148 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 notanpe 252 thread_crypt64_new(void *a_param)
387 notanpe 148 {
388 notanpe 252 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 notanpe 148
396 notanpe 252 WaitForSingleObject(mutex_key, INFINITE);
397 notanpe 148
398 notanpe 252 ploop = &loop_cpu[n_cpus++];
399 notanpe 148
400 notanpe 252 srand(usec() ^ param->seed ^ (unsigned)th);
401     key_init(&key);
402     ReleaseMutex(mutex_key);
403 notanpe 148
404     #ifdef thread_set_priority
405 notanpe 252 thread_set_priority(th, param->pri);
406 notanpe 148 #endif
407    
408 notanpe 252 for (;;)
409     {
410     do
411 notanpe 148 {
412 notanpe 252 int j;
413     for (j = 0; j < 8; j++)
414 notanpe 148 {
415 notanpe 252 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 notanpe 148 }
418 notanpe 252 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 notanpe 148 }
427 notanpe 252 while (key_inc(&key, 6, 8) || key_inc(&key, KEY_SHUFFLE_POS, 8));
428 notanpe 254 DPRINT( "saaaaalt chaaaaange\n" );
429 notanpe 148
430 notanpe 252 WaitForSingleObject(mutex_key, INFINITE);
431     key_reset(&key, 0);
432     ReleaseMutex(mutex_key);
433 notanpe 148 }
434    
435 notanpe 252 /* notreached */
436 notanpe 250 }
437    
438 notanpe 254 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 notanpe 148 /***************************************************************
487     *
488     * メインループとか
489     *
490     */
491    
492     int
493 chapuni 1 main(int argc, char *argv[])
494     {
495 chapuni 74 int i;
496 chapuni 1 int mincnt;
497 notanpe 148 CODE_T *code = NULL;
498 notanpe 253 long code_cmp;
499 chapuni 46 FILE *sfp; /* scoreboard */
500     struct ITREE *root_expr;
501 notanpe 148 uint64_t proc_mask;
502     struct THREAD_PARAM *threads = NULL;
503     int nthreads;
504     int tn;
505 chapuni 1 int cr;
506    
507 notanpe 148 /* 鍵文字列 */
508 notanpe 252 struct KS_KEY key;
509 notanpe 148
510 notanpe 119 #define UPDATE_INTERVAL 8 /* 速度表示の間隔 秒 */
511 notanpe 115 struct status {
512 notanpe 192 uint64_t startTime; /* 開始時刻 ミリ秒 */
513     uint64_t lastTime; /* 最後に表示した時刻 ミリ秒 */
514     uint64_t loop; /* 総検索個数 */
515     uint64_t lastloop; /* 最後に表示した時の loop */
516 notanpe 115 } status;
517 notanpe 192 uint64_t curTime;
518     uint32_t upd_int = 0;
519 notanpe 252 /*
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 chapuni 1
527 notanpe 252 if (!cpuid_issupported())
528     {
529     fprintf(stderr, "この環境で走らせることが想定されていません。\n");
530     exit(1);
531     }
532 notanpe 197
533 notanpe 254 {
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 notanpe 252 assert((1 << N_STRIDE) == N_ALU * ALU_BITS);
663 notanpe 197
664 notanpe 252 mutex_key = CreateMutex(NULL, FALSE, NULL);
665 notanpe 197
666 chapuni 46 /* タゲ読み込み */
667 notanpe 252 root_expr = expr_parse("target.txt");
668 chapuni 2
669 notanpe 148 /* コードを生成・展開
670     起動予定スレッド数に応じて
671     生成するコードを変える */
672 chapuni 46 sfp = scoreboard_open();
673 notanpe 252 fwrite(crypt64_descs[0]->pro, 1, crypt64_descs[0]->cmp_pro - crypt64_descs[0]->pro, sfp); /* prologue & コアループ */
674 notanpe 197
675 notanpe 252 #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 notanpe 214
687 notanpe 252 /* 比較器のみを生成(前半) */
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 notanpe 214
694 notanpe 252 /* 比較部を生成 */
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 notanpe 214
699 chapuni 46 /* コードをメモリに貼り付ける */
700 notanpe 252 code = scoreboard_map(sfp);
701 chapuni 1
702     /* キーの初期化 */
703 notanpe 252 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 notanpe 222
709 notanpe 252 if (log_open("log.txt") != 0) return 1;
710 notanpe 222
711 notanpe 252 WaitForSingleObject(mutex_key, INFINITE);
712 notanpe 222
713 notanpe 148 /* 働くおじさんを量産 */
714     nthreads = 0;
715 notanpe 252 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 notanpe 148 #ifdef WIN32
728 notanpe 252 h = GetCurrentProcess();
729     SetPriorityClass(h, BELOW_NORMAL_PRIORITY_CLASS);
730 chapuni 1 #endif
731 notanpe 252 #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 notanpe 148 #endif
740 notanpe 252 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 notanpe 148 #ifdef thread_set_priority
753 notanpe 252 //threads[nthreads].pri = THREAD_PRIORITY_BELOW_NORMAL;
754     threads[nthreads].pri = THREAD_PRIORITY_LOWEST;
755 notanpe 148 #endif
756 notanpe 252 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 notanpe 148 #ifdef thread_set_priority
767 notanpe 252 threads[nthreads].pri = THREAD_PRIORITY_IDLE;
768 notanpe 148 #endif
769 notanpe 252 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 notanpe 148
783 notanpe 252 fprintf(stderr, "検索開始!\n");
784     ReleaseMutex(mutex_key);
785 chapuni 1
786 notanpe 252 mincnt = 0x7FFFFFFF;
787 notanpe 198
788 chapuni 1 cr = 0;
789 notanpe 120 memset( &status, 0, sizeof( struct status ) );
790 notanpe 119 status.startTime = status.lastTime = usec();
791 notanpe 213
792 notanpe 252 /* 探索ループだぞっと */
793     for (;;)
794     {
795     Sleep(5000);
796 notanpe 213
797 notanpe 252 /* 速度計測 */
798     status.loop = 0;
799     for (i = 0; i < n_cpus; i++) status.loop += loop_cpu[i];
800 notanpe 237
801 notanpe 252 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 notanpe 237
810 notanpe 252 /* 区間(単位 trips/sec) */
811     diffTime = curTime - status.lastTime;
812     b = USEC_SEC * (status.loop - status.lastloop) / diffTime;
813 chapuni 1
814 notanpe 252 /* 予測 */
815     c = UPDATE_INTERVAL * b;
816 notanpe 148
817 notanpe 252 /* 立ち上がりなど、誤差があり upd_int が小さすぎたときは
818     いきなり全補正せず 1 秒(==b)づつ収斂させる。 */
819     upd_int = (upd_int + b < c
820     ? upd_int + b
821     : c);
822 chapuni 1
823 notanpe 252 status.lastTime = curTime;
824     status.lastloop = status.loop;
825 notanpe 148 #if DEBUG>=1
826 notanpe 252 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 notanpe 148 #endif
839 notanpe 252 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 notanpe 198
847 chapuni 1 return 0;
848     }
849    
850 chapuni 2 /*
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