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