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