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 263 - (hide annotations) (download) (as text)
Mon Jul 4 09:42:05 2011 UTC (12 years, 9 months ago) by notanpe
File MIME type: text/x-csrc
File size: 22821 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 notanpe 263 #include "makai.h"
37 chapuni 1
38 notanpe 254 #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 notanpe 256 #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 notanpe 258 /* 塩固定 */
64     char fixedSalt[3]; /* log_print で使うので大域変数 */
65     #define NUMSC 64 /* 塩の文字種数 */
66     static char saltChar[NUMSC] = "abcdefghijklmnopqrstuvwxyz"
67     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
68     "0123456789./";
69    
70 notanpe 252 static HANDLE mutex_key;
71 notanpe 198
72 notanpe 192 /* CRYPT64 記述子 */
73     static
74     struct CRYPT64_DESC const *const crypt64_descs[] =
75     {
76     &crypt64_desc,
77     };
78    
79 notanpe 252 /* 速度評価用 */
80     static int n_cpus;
81     static uint64_t loop_cpu[1024];
82 chapuni 1
83 notanpe 192 #define USEC_SEC 1000 /* 1秒 */
84    
85 chapuni 1 static
86 notanpe 192 uint64_t
87 notanpe 148 usec(void)
88 notanpe 119 {
89 notanpe 120 uint32_t sec, msec;
90    
91 notanpe 119 #if !defined(WIN32)
92     struct timeval tv;
93     gettimeofday(&tv, NULL);
94 notanpe 120 sec = tv.tv_sec;
95 notanpe 192 msec = tv.tv_usec / (1000000 / USEC_SEC);
96 notanpe 119 #else
97     struct timeb tm;
98     ftime(&tm);
99 notanpe 120 sec = tm.time;
100 notanpe 192 msec = tm.millitm / (1000 / USEC_SEC);
101 notanpe 119 #endif
102 notanpe 120
103 notanpe 192 return (uint64_t)USEC_SEC * sec + msec;
104 notanpe 119 }
105    
106 chapuni 1 /***************************************************************
107     *
108 notanpe 192 * CPU capabilities を取得
109     * [XXX] あまりにも古いプロセッサのことは考えない。
110 chapuni 1 *
111 notanpe 192 * a[4] = {EAX,EBX,ECX,EDX}
112     *
113 chapuni 1 */
114    
115 notanpe 192 #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 notanpe 148 {
134 notanpe 192 unsigned a, b, c, d;
135     cpuid(1, a, b, c, d);
136     return d;
137     }
138 chapuni 1
139 notanpe 148 static
140 notanpe 192 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 notanpe 148 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 notanpe 192 intptr_t a = 128;
163 notanpe 148 struct PACKET_CRYPT64 *pkts;
164     assert(IS_POWER2(sizeof(struct PACKET_CRYPT64)));
165     assert(n >= 1);
166    
167 notanpe 192 siz = (a - 1
168 notanpe 148 + (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 notanpe 192 + a - 1)
174     & -a);
175 notanpe 148 #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 notanpe 192 int j, k;
189 notanpe 148
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 notanpe 192 for (k = 0; k < N_ALU; k++)
200     pkts[i].key64.ks[j].a[k] = sizeof(WS_T) * ks_ls[j];
201 notanpe 148
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 notanpe 252 #elif defined(_POSIX_SOURCE)
274 notanpe 148
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 notanpe 260 #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 notanpe 148
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 notanpe 253 long code_cmp;
341 notanpe 252 unsigned seed;
342 notanpe 148
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 notanpe 254 #if 0
372 notanpe 148 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 notanpe 254 #endif /* 0 */
383 notanpe 148 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 notanpe 252 thread_crypt64_new(void *a_param)
409 notanpe 148 {
410 notanpe 252 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 notanpe 256 int lc;
418 notanpe 148
419 notanpe 252 WaitForSingleObject(mutex_key, INFINITE);
420 notanpe 148
421 notanpe 256 OLDPRINT( "n_cpus %d\n", n_cpus );
422 notanpe 252 ploop = &loop_cpu[n_cpus++];
423 notanpe 258 lc = 0;
424 notanpe 148
425 notanpe 258 OLDPRINT( "(unsigned)th %u\n", (unsigned)th );
426     OLDPRINT( "param->seed %u\n", param->seed );
427     /* th はスレッドが違っても同じ値になってる */
428 notanpe 252 srand(usec() ^ param->seed ^ (unsigned)th);
429     key_init(&key);
430 notanpe 258
431 notanpe 252 ReleaseMutex(mutex_key);
432 notanpe 148
433     #ifdef thread_set_priority
434 notanpe 252 thread_set_priority(th, param->pri);
435 notanpe 148 #endif
436    
437 notanpe 258 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 notanpe 252 for (;;)
482     {
483     do
484 notanpe 148 {
485 notanpe 252 int j;
486     for (j = 0; j < 8; j++)
487 notanpe 148 {
488 notanpe 252 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 notanpe 148 }
491 notanpe 252 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 notanpe 256 (*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 notanpe 148 }
511 notanpe 252 while (key_inc(&key, 6, 8) || key_inc(&key, KEY_SHUFFLE_POS, 8));
512 notanpe 256 OLDPRINT( "saaaaalt chaaaaange\n" );
513 notanpe 148
514 notanpe 252 WaitForSingleObject(mutex_key, INFINITE);
515     key_reset(&key, 0);
516     ReleaseMutex(mutex_key);
517 notanpe 148 }
518    
519 notanpe 252 /* notreached */
520 notanpe 250 }
521    
522 notanpe 254 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 notanpe 258 printf( "%s [-h] [-v] [-p num] [-t num|-m mask] [-g num] [-z]\n", myName );
555 notanpe 254 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 notanpe 256 printf( " -g num : がんばりぐあい ( %d (やる気なし) ≦ num ≦ %d (フルパワー), デフォルトは、%d )\n", GEAR_MIN, GEAR_MAX, GEAR_DEF );
569 notanpe 258 printf( " -z : 全空間モード\n" );
570 notanpe 254 }
571    
572 notanpe 148 /***************************************************************
573     *
574     * メインループとか
575     *
576     */
577    
578     int
579 chapuni 1 main(int argc, char *argv[])
580     {
581 chapuni 74 int i;
582 notanpe 148 CODE_T *code = NULL;
583 notanpe 253 long code_cmp;
584 chapuni 46 FILE *sfp; /* scoreboard */
585     struct ITREE *root_expr;
586 notanpe 148 uint64_t proc_mask;
587 notanpe 256 int nThread;
588 notanpe 148 struct THREAD_PARAM *threads = NULL;
589     int nthreads;
590     int tn;
591 notanpe 256 int aveSpeed, spanSpeed, bestSpeed;
592     int gear;
593     int sCnt;
594     int tmplCntMax;
595     int maxSrchCnt;
596 notanpe 260 int verbose;
597     DWORD priority;
598 chapuni 1
599 notanpe 148 /* 鍵文字列 */
600 notanpe 252 struct KS_KEY key;
601 notanpe 148
602 notanpe 119 #define UPDATE_INTERVAL 8 /* 速度表示の間隔 秒 */
603 notanpe 115 struct status {
604 notanpe 192 uint64_t startTime; /* 開始時刻 ミリ秒 */
605     uint64_t lastTime; /* 最後に表示した時刻 ミリ秒 */
606     uint64_t loop; /* 総検索個数 */
607     uint64_t lastloop; /* 最後に表示した時の loop */
608 notanpe 115 } status;
609 notanpe 192 uint64_t curTime;
610 chapuni 1
611 notanpe 258 #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 notanpe 252 if (!cpuid_issupported())
621     {
622     fprintf(stderr, "この環境で走らせることが想定されていません。\n");
623     exit(1);
624     }
625 notanpe 197
626 notanpe 254 {
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 notanpe 256 gear = GEAR_DEF;
642 notanpe 258 fixedSalt[0] = fixedSalt[1] = fixedSalt[2] = '\0';
643 notanpe 254
644 notanpe 258 /* 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 notanpe 254 switch ( optChar ) {
648 notanpe 256 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 notanpe 254 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 notanpe 258 case 'z':
704     srand( usec() );
705     fixedSalt[0] = saltChar[rand() % NUMSC];
706     fixedSalt[1] = saltChar[rand() % NUMSC];
707     break;
708 notanpe 254 default:
709     usage( argv[0] );
710     exit( 1 );
711     }
712     }
713    
714 notanpe 262 #ifdef MAKEY
715     fprintf(stderr, "魔キー空間バージョンにつき、シロウトにはおすすめできない。\n\n");
716     #endif /* MAKEY */
717    
718 notanpe 254 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 notanpe 257 if ( gear != GEAR_MAX ) {
746 notanpe 258 /* CPU 使用率が正しく見えるように、秘孔をついてみる */
747 notanpe 257 TIMECAPS tc;
748     if ( timeGetDevCaps( &tc, sizeof( TIMECAPS ) ) == MMSYSERR_NOERROR ) {
749     timeBeginPeriod( tc.wPeriodMin );
750     }
751     }
752    
753 notanpe 256 nThread = popcnt64( proc_mask );
754     printf( "%d 個の検索スレッドを起動\n", nThread );
755 notanpe 260 }
756 notanpe 257
757 notanpe 260 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 notanpe 254 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 notanpe 256 if ( gear == GEAR_MAX ) {
785     printf( "CPU を 100%% 使用\n" );
786     } else {
787     printf( "CPU を %d 割ぐらい使用\n", gear );
788     }
789 notanpe 258 if ( fixedSalt[0] != '\0' ) {
790     printf( "全空間モード (salt:%c%c)\n", fixedSalt[0], fixedSalt[1] );
791     }
792 notanpe 263 #ifdef KEYLOG
793     if ( keyLog == MAKAI_TRUE ) {
794     printf( "検索したキー空間のロギング\n" );
795     initMutexKeylog();
796     }
797     #endif /* KEYLOG */
798 notanpe 260 #ifdef SPECIAL
799     dispSpecial();
800     #else /* SPECIAL */
801     printf( "特殊検索は無効化されています\n" );
802     #endif /* SPECIAL */
803 notanpe 254 }
804    
805     #ifdef WIN32
806 notanpe 260 /* 【注意】priority を上書きしている */
807 notanpe 254 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 notanpe 148 /* コードを生成・展開
816     起動予定スレッド数に応じて
817     生成するコードを変える */
818 chapuni 46 sfp = scoreboard_open();
819 notanpe 252 fwrite(crypt64_descs[0]->pro, 1, crypt64_descs[0]->cmp_pro - crypt64_descs[0]->pro, sfp); /* prologue & コアループ */
820 notanpe 197
821 notanpe 252 #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 notanpe 214
833 notanpe 252 /* 比較器のみを生成(前半) */
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 notanpe 214
840 notanpe 252 /* 比較部を生成 */
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 notanpe 214
845 chapuni 46 /* コードをメモリに貼り付ける */
846 notanpe 252 code = scoreboard_map(sfp);
847 chapuni 1
848 notanpe 263 /* salt を設定するためにダミーのキーを作成 (ここってロックいるのか ?) */
849 notanpe 252 WaitForSingleObject(mutex_key, INFINITE);
850 notanpe 263 key.key[1] = 'z' + 1;
851     key.key[2] = 'z' + 1;
852 notanpe 252 ReleaseMutex(mutex_key);
853     set_salt(code, crypt64_descs[0], key.key);
854 notanpe 222
855 notanpe 252 if (log_open("log.txt") != 0) return 1;
856 notanpe 222
857 notanpe 252 WaitForSingleObject(mutex_key, INFINITE);
858 notanpe 222
859 notanpe 148 /* 働くおじさんを量産 */
860     nthreads = 0;
861 notanpe 252 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 notanpe 148 #ifdef WIN32
874 notanpe 252 h = GetCurrentProcess();
875     SetPriorityClass(h, BELOW_NORMAL_PRIORITY_CLASS);
876 chapuni 1 #endif
877 notanpe 252 #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 notanpe 148 #endif
886 notanpe 252 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 notanpe 148 #ifdef thread_set_priority
899 notanpe 252 //threads[nthreads].pri = THREAD_PRIORITY_BELOW_NORMAL;
900     threads[nthreads].pri = THREAD_PRIORITY_LOWEST;
901 notanpe 148 #endif
902 notanpe 252 thread_create(h, thread_crypt64_new, &threads[nthreads]);
903     #ifdef thread_get_tid
904     thread_set_affinity(h, i);
905     #endif
906     nthreads++;
907 notanpe 256 #if 0
908 notanpe 252 /* IDLE */
909     threads[nthreads].code = code;
910     threads[nthreads].code_cmp = code_cmp;
911     threads[nthreads].seed = rand();
912 notanpe 148 #ifdef thread_set_priority
913 notanpe 252 threads[nthreads].pri = THREAD_PRIORITY_IDLE;
914 notanpe 148 #endif
915 notanpe 252 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 notanpe 148
929 notanpe 252 fprintf(stderr, "検索開始!\n");
930     ReleaseMutex(mutex_key);
931 chapuni 1
932 notanpe 120 memset( &status, 0, sizeof( struct status ) );
933 notanpe 119 status.startTime = status.lastTime = usec();
934 notanpe 213
935 notanpe 256 bestSpeed = 0;
936     sCnt = 0;
937     lCntMax = 0;
938     maxSrchCnt = 0;
939     for ( ;; ) {
940     uint64_t diffTime;
941 notanpe 258 uint64_t spanLoop;
942 notanpe 213
943 notanpe 256 Sleep(STS_SPAN);
944    
945     #ifdef OLDEBUG
946     putchar( '\n' );
947     #endif /* DEBUG */
948 notanpe 252 status.loop = 0;
949 notanpe 256 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 notanpe 237
955 notanpe 256 spanLoop = status.loop - status.lastloop;
956     if ( spanLoop > maxSrchCnt ) {
957     maxSrchCnt = spanLoop;
958     }
959 notanpe 237
960 notanpe 256 curTime = usec();
961 chapuni 1
962 notanpe 256 /* 通算 (単位 trips/usec = ktrips/sec) */
963     diffTime = curTime - status.startTime;
964     aveSpeed = status.loop / diffTime;
965 notanpe 148
966 notanpe 256 /* 区間 (単位 trips/usec = ktrips/sec) */
967     diffTime = curTime - status.lastTime;
968     spanSpeed = spanLoop / diffTime;
969 chapuni 1
970 notanpe 256 /* 最速 */
971     if ( spanSpeed > bestSpeed ) {
972     bestSpeed = spanSpeed;
973     if ( gear != GEAR_MAX ) {
974 notanpe 258 tmplCntMax = ((maxSrchCnt / (N_ALU * ALU_BITS)) * gear / 10) / ((STS_SPAN - (STS_SPAN * gear / 10)) / GEAR_SLEEP) / nThread;
975 notanpe 256 }
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 notanpe 252 }
998 notanpe 198
999 chapuni 1 return 0;
1000     }
1001    
1002 chapuni 2 /*
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