Rev 108 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 108 | Rev 154 | ||
---|---|---|---|
Line 2... | Line 2... | ||
2 | #include "data.h" |
2 | #include "data.h" |
3 | #include "epdglue.h" |
3 | #include "epdglue.h" |
4 | #if (CPUS > 1) |
- | |
5 | /* modified |
4 | /* modified 08/03/16 */ |
6 | /* |
5 | /* |
7 | ******************************************************************************* |
6 | ******************************************************************************* |
8 | * * |
7 | * * |
9 | * Split() is the driver for the threaded parallel search in Crafty. The * |
8 | * Split() is the driver for the threaded parallel search in Crafty. The * |
10 | * basic idea is that whenever we notice that one (or more) threads are in * |
9 | * basic idea is that whenever we notice that one (or more) threads are in * |
Line 74... | Line 73... | ||
74 | * * |
73 | * * |
75 | * There are a number of settable options via the command-line or .craftyrc * |
74 | * There are a number of settable options via the command-line or .craftyrc * |
76 | * initialization file. Here's a concise explanation for each option and an * |
75 | * initialization file. Here's a concise explanation for each option and an * |
77 | * occasional suggestion for testing/tuning. * |
76 | * occasional suggestion for testing/tuning. * |
78 | * * |
77 | * * |
79 | * smp_affinity (command = smpaffinity=<n> is |
78 | * smp_affinity (command = smpaffinity=<n> <p> is used to enable or disable * |
80 | * processor affinity. -1 disables affinity and lets threads run on any * |
79 | * processor affinity. -1 disables affinity and lets threads run on any * |
81 | * available core. If you use an integer <n> then thread zero will bind * |
80 | * available core. If you use an integer <n> then thread zero will bind * |
82 | * itself to cpu <n> and each additional thread will bind to the next * |
81 | * itself to cpu <n> and each additional thread will bind to the next * |
83 | * higher cpu number. This is useful if you try to run two copies of * |
82 | * higher cpu number. This is useful if you try to run two copies of * |
84 | * crafty on the same machine, now you can cause one to bind to the first * |
83 | * crafty on the same machine, now you can cause one to bind to the first * |
Line 197... | Line 196... | ||
197 | * * |
196 | * * |
198 | ************************************************************ |
197 | ************************************************************ |
199 | */ |
198 | */ |
200 | tstart = ReadClock(); |
199 | tstart = ReadClock(); |
201 | tree->nprocs = 0; |
200 | tree->nprocs = 0; |
202 | for (tid = 0; tid < |
201 | for (tid = 0; tid < smp_max_threads; tid++) |
203 | tree->siblings[tid] = 0; |
202 | tree->siblings[tid] = 0; |
204 | child = GetBlock(tree, tree->thread_id); |
203 | child = GetBlock(tree, tree->thread_id); |
205 | if (!child) |
204 | if (!child) |
206 | return 0; |
205 | return 0; |
207 | CopyFromParent(child); |
206 | CopyFromParent(child); |
Line 240... | Line 239... | ||
240 | if (!tree->joined) |
239 | if (!tree->joined) |
241 | parallel_splits_wasted++; |
240 | parallel_splits_wasted++; |
242 | return 1; |
241 | return 1; |
243 | } |
242 | } |
244 | 243 | ||
245 | /* modified |
244 | /* modified 08/03/16 */ |
246 | /* |
245 | /* |
247 | ******************************************************************************* |
246 | ******************************************************************************* |
248 | * * |
247 | * * |
249 | * Join() is called just when we enter the usual spin-loop waiting for work. * |
248 | * Join() is called just when we enter the usual spin-loop waiting for work. * |
250 | * We take a quick look at all active split blocks to see if any look * |
249 | * We take a quick look at all active split blocks to see if any look * |
Line 282... | Line 281... | ||
282 | * joinable once we acquire the lock, we abort joining * |
281 | * joinable once we acquire the lock, we abort joining * |
283 | * since it is futile. Note that if this happens, we will * |
282 | * since it is futile. Note that if this happens, we will * |
284 | * try to find an existing split point we can join three * |
283 | * try to find an existing split point we can join three * |
285 | * times before we exit, setting split to 1 to ask other * |
284 | * times before we exit, setting split to 1 to ask other * |
286 | * threads to produce more candidate split points. * |
285 | * threads to produce more candidate split points. * |
- | 286 | * * |
|
- | 287 | * Special case: We don't want to join a split point that * |
|
- | 288 | * was created by this thread. While it works, it can add * |
|
- | 289 | * overhead since we can encounter a later split point * |
|
- | 290 | * that originated at the current split point, and we * |
|
- | 291 | * would continue searching even though most of the work * |
|
- | 292 | * has already been completed. The hash table would help * |
|
- | 293 | * avoid most (if not all) of this overhead, but there is * |
|
- | 294 | * no good reason to take the chance of this happening. * |
|
287 | * * |
295 | * * |
288 | ************************************************************ |
296 | ************************************************************ |
289 | */ |
297 | */ |
290 | for (pass = 0; pass < 3; pass++) { |
298 | for (pass = 0; pass < 3; pass++) { |
291 | best_interest = -999999; |
299 | best_interest = -999999; |
292 | join_block = 0; |
300 | join_block = 0; |
293 | for (current = 0; current <= |
301 | for (current = 0; current <= smp_max_threads * 64; current++) { |
294 | tree = block[current]; |
302 | tree = block[current]; |
295 | if (tree->joinable && (tree->ply <= tree->depth / 2 || |
303 | if (tree->joinable && (tree->ply <= tree->depth / 2 || |
296 | tree->nprocs < |
304 | tree->nprocs < smp_split_group) && tree->thread_id != tid) { |
297 | interest = tree->depth * 2 - tree->searched[0]; |
305 | interest = tree->depth * 2 - tree->searched[0]; |
298 | if (interest > best_interest) { |
306 | if (interest > best_interest) { |
299 | best_interest = interest; |
307 | best_interest = interest; |
300 | join_block = tree; |
308 | join_block = tree; |
301 | } |
309 | } |
Line 336... | Line 344... | ||
336 | ************************************************************ |
344 | ************************************************************ |
337 | */ |
345 | */ |
338 | if (join_block) { |
346 | if (join_block) { |
339 | Lock(join_block->lock); |
347 | Lock(join_block->lock); |
340 | if (join_block->joinable) { |
348 | if (join_block->joinable) { |
341 | child = GetBlock(join_block, |
349 | child = GetBlock(join_block, tid); |
342 | Unlock(join_block->lock); |
350 | Unlock(join_block->lock); |
343 | if (child) { |
351 | if (child) { |
344 | CopyFromParent(child); |
352 | CopyFromParent(child); |
345 | thread[tid].tree = child; |
353 | thread[tid].tree = child; |
346 | parallel_joins++; |
354 | parallel_joins++; |
Line 363... | Line 371... | ||
363 | */ |
371 | */ |
364 | smp_split = 1; |
372 | smp_split = 1; |
365 | return 0; |
373 | return 0; |
366 | } |
374 | } |
367 | 375 | ||
368 | /* modified |
376 | /* modified 08/03/16 */ |
- | 377 | /* |
|
- | 378 | ******************************************************************************* |
|
- | 379 | * * |
|
- | 380 | * ThreadAffinity() is called to "pin" a thread to a specific processor. It * |
|
- | 381 | * is a "noop" (no-operation) if Crafty was not compiled with -DAFFINITY, or * |
|
- | 382 | * if smp_affinity is negative (smpaffinity=-1 disables affinity). It * |
|
- | 383 | * simply sets the affinity for the current thread to the requested CPU and * |
|
- | 384 | * returns. NOTE: If hyperthreading is enabled, there is no guarantee that * |
|
- | 385 | * this will work as expected and pin one thread per physical core. It * |
|
- | 386 | * depends on how the O/S numbers the SMT cores. * |
|
- | 387 | * * |
|
- | 388 | ******************************************************************************* |
|
- | 389 | */ |
|
- | 390 | void ThreadAffinity(int cpu) { |
|
- | 391 | #if defined(AFFINITY) |
|
- | 392 | cpu_set_t cpuset; |
|
- | 393 | pthread_t current_thread = pthread_self(); |
|
- | 394 | ||
- | 395 | if (smp_affinity >= 0) { |
|
- | 396 | CPU_ZERO(&cpuset); |
|
- | 397 | CPU_SET(smp_affinity_increment * (cpu + smp_affinity), &cpuset); |
|
- | 398 | pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset); |
|
- | 399 | } |
|
- | 400 | #endif |
|
- | 401 | } |
|
- | 402 | ||
- | 403 | /* modified 08/03/16 */ |
|
369 | /* |
404 | /* |
370 | ******************************************************************************* |
405 | ******************************************************************************* |
371 | * * |
406 | * * |
372 | * ThreadInit() is called after a process is created. Its main task is to * |
407 | * ThreadInit() is called after a process is created. Its main task is to * |
373 | * initialize the process local memory so that it will fault in and be * |
408 | * initialize the process local memory so that it will fault in and be * |
Line 380... | Line 415... | ||
380 | */ |
415 | */ |
381 | void *STDCALL ThreadInit(void *t) { |
416 | void *STDCALL ThreadInit(void *t) { |
382 | int tid = (int64_t) t; |
417 | int tid = (int64_t) t; |
383 | 418 | ||
384 | ThreadAffinity(tid); |
419 | ThreadAffinity(tid); |
385 |
|
420 | #if !defined(UNIX) |
386 | ThreadMalloc((uint64_t) tid); |
421 | ThreadMalloc((uint64_t) tid); |
387 |
|
422 | #endif |
388 | thread[tid].blocks = 0xffffffffffffffffull; |
423 | thread[tid].blocks = 0xffffffffffffffffull; |
389 | Lock(lock_smp); |
424 | Lock(lock_smp); |
390 | initialized_threads++; |
425 | initialized_threads++; |
391 | Unlock(lock_smp); |
426 | Unlock(lock_smp); |
392 | WaitForAllThreadsInitialized(); |
427 | WaitForAllThreadsInitialized(); |
Line 395... | Line 430... | ||
395 | smp_threads--; |
430 | smp_threads--; |
396 | Unlock(lock_smp); |
431 | Unlock(lock_smp); |
397 | return 0; |
432 | return 0; |
398 | } |
433 | } |
399 | 434 | ||
400 | /* modified |
435 | /* modified 08/03/16 */ |
401 | /* |
- | |
402 | ******************************************************************************* |
- | |
403 | * * |
- | |
404 | * ThreadAffinity() is called to "pin" a thread to a specific processor. It * |
- | |
405 | * is a "noop" (no-operation) if Crafty was not compiled with -DAFFINITY, or * |
- | |
406 | * if smp_affinity is negative (smpaffinity=-1 disables affinity). It * |
- | |
407 | * simply sets the affinity for the current thread to the requested CPU and * |
- | |
408 | * returns. NOTE: If hyperthreading is enabled, there is no guarantee that * |
- | |
409 | * this will work as expected and pin one thread per physical core. It * |
- | |
410 | * depends on how the O/S numbers the SMT cores. * |
- | |
411 | * * |
- | |
412 | ******************************************************************************* |
- | |
413 | */ |
- | |
414 | void ThreadAffinity(int cpu) { |
- | |
415 | # if defined(AFFINITY) |
- | |
416 | cpu_set_t cpuset; |
- | |
417 | pthread_t current_thread = pthread_self(); |
- | |
418 | - | ||
419 | if (smp_affinity >= 0) { |
- | |
420 | CPU_ZERO(&cpuset); |
- | |
421 | CPU_SET(cpu + smp_affinity, &cpuset); |
- | |
422 | pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset); |
- | |
423 | } |
- | |
424 | # endif |
- | |
425 | } |
- | |
426 | - | ||
427 | /* modified 11/04/15 */ |
- | |
428 | /* |
436 | /* |
429 | ******************************************************************************* |
437 | ******************************************************************************* |
430 | * * |
438 | * * |
431 | * ThreadSplit() is used to determine if we should split at the current ply. * |
439 | * ThreadSplit() is used to determine if we should split at the current ply. * |
432 | * There are some basic constraints on when splits can be done, such as the * |
440 | * There are some basic constraints on when splits can be done, such as the * |
Line 441... | Line 449... | ||
441 | * thread becomes idle, it will find these split points immediately and not * |
449 | * thread becomes idle, it will find these split points immediately and not * |
442 | * have to wait for a split after the fact. * |
450 | * have to wait for a split after the fact. * |
443 | * * |
451 | * * |
444 | ******************************************************************************* |
452 | ******************************************************************************* |
445 | */ |
453 | */ |
446 | int ThreadSplit(TREE * |
454 | int ThreadSplit(TREE * tree, int ply, int depth, int alpha, int o_alpha, |
447 | int done) { |
455 | int done) { |
448 | TREE *used; |
456 | TREE *used; |
449 | int64_t tblocks; |
457 | int64_t tblocks; |
450 | int temp, unused = 0; |
458 | int temp, unused = 0; |
451 | 459 | ||
Line 456... | Line 464... | ||
456 | * split point, that being that we must not be too far * |
464 | * split point, that being that we must not be too far * |
457 | * from the root (smp_min_split_depth). * |
465 | * from the root (smp_min_split_depth). * |
458 | * * |
466 | * * |
459 | ************************************************************ |
467 | ************************************************************ |
460 | */ |
468 | */ |
461 | if (depth < |
469 | if (depth < smp_min_split_depth) |
462 | return 0; |
470 | return 0; |
463 | /* |
471 | /* |
464 | ************************************************************ |
472 | ************************************************************ |
465 | * * |
473 | * * |
466 | * If smp_split is NOT set, we are checking to see if it * |
474 | * If smp_split is NOT set, we are checking to see if it * |
Line 482... | Line 490... | ||
482 | * just add to the overhead with no benefit. * |
490 | * just add to the overhead with no benefit. * |
483 | * * |
491 | * * |
484 | ************************************************************ |
492 | ************************************************************ |
485 | */ |
493 | */ |
486 | if (!smp_split) { |
494 | if (!smp_split) { |
487 | if (depth < |
495 | if (depth < smp_gratuitous_depth || done > 1) |
488 | return 0; |
496 | return 0; |
489 | tblocks = ~thread[tree->thread_id].blocks; |
497 | tblocks = ~thread[tree->thread_id].blocks; |
490 | while (tblocks) { |
498 | while (tblocks) { |
491 | temp = LSB(tblocks); |
499 | temp = LSB(tblocks); |
492 | used = block[temp + tree->thread_id * 64 + 1]; |
500 | used = block[temp + tree->thread_id * 64 + 1]; |
493 | if (used->joinable && !used->joined) |
501 | if (used->joinable && !used->joined) |
494 | unused++; |
502 | unused++; |
495 | Clear(temp, tblocks); |
503 | Clear(temp, tblocks); |
496 | } |
504 | } |
497 | if (unused > |
505 | if (unused > smp_gratuitous_limit) |
498 | return 0; |
506 | return 0; |
499 | } |
507 | } |
500 | /* |
508 | /* |
501 | ************************************************************ |
509 | ************************************************************ |
502 | * * |
510 | * * |
Line 525... | Line 533... | ||
525 | used = block[temp + tree->thread_id * 64 + 1]; |
533 | used = block[temp + tree->thread_id * 64 + 1]; |
526 | if (used->joinable && !used->joined) |
534 | if (used->joinable && !used->joined) |
527 | unused++; |
535 | unused++; |
528 | Clear(temp, tblocks); |
536 | Clear(temp, tblocks); |
529 | } |
537 | } |
530 | if (unused > |
538 | if (unused > smp_gratuitous_limit) |
531 | return 0; |
539 | return 0; |
532 | } |
540 | } |
533 | return 1; |
541 | return 1; |
534 | } |
542 | } |
535 | 543 | ||
536 | /* modified |
544 | /* modified 08/03/16 */ |
537 | /* |
545 | /* |
538 | ******************************************************************************* |
546 | ******************************************************************************* |
539 | * * |
547 | * * |
540 | * ThreadStop() is called from SearchMoveList() when it detects a beta * |
548 | * ThreadStop() is called from SearchMoveList() when it detects a beta * |
541 | * cutoff (fail high) at a node that is being searched in parallel. We need * |
549 | * cutoff (fail high) at a node that is being searched in parallel. We need * |
Line 551... | Line 559... | ||
551 | int proc; |
559 | int proc; |
552 | 560 | ||
553 | Lock(tree->lock); |
561 | Lock(tree->lock); |
554 | tree->stop = 1; |
562 | tree->stop = 1; |
555 | tree->joinable = 0; |
563 | tree->joinable = 0; |
556 | for (proc = 0; proc < |
564 | for (proc = 0; proc < smp_max_threads; proc++) |
557 | if (tree->siblings[proc]) |
565 | if (tree->siblings[proc]) |
558 | ThreadStop(tree->siblings[proc]); |
566 | ThreadStop(tree->siblings[proc]); |
559 | Unlock(tree->lock); |
567 | Unlock(tree->lock); |
560 | } |
568 | } |
561 | 569 | ||
562 | /* modified |
570 | /* modified 08/03/16 */ |
563 | /* |
571 | /* |
564 | ******************************************************************************* |
572 | ******************************************************************************* |
565 | * * |
573 | * * |
566 | * ThreadTrace() is a debugging tool that simply walks the split block tree * |
574 | * ThreadTrace() is a debugging tool that simply walks the split block tree * |
567 | * and displays interesting data to help debug the parallel search whenever * |
575 | * and displays interesting data to help debug the parallel search whenever * |
Line 595... | Line 603... | ||
595 | if (!brief) { |
603 | if (!brief) { |
596 | for (i = 0; i < 4 * depth; i++) |
604 | for (i = 0; i < 4 * depth; i++) |
597 | Print(4095, " "); |
605 | Print(4095, " "); |
598 | Print(4095, " parent=%d sibling threads=", |
606 | Print(4095, " parent=%d sibling threads=", |
599 | FindBlockID(tree->parent)); |
607 | FindBlockID(tree->parent)); |
600 | for (proc = 0; proc < |
608 | for (proc = 0; proc < smp_max_threads; proc++) |
601 | if (tree->siblings[proc]) |
609 | if (tree->siblings[proc]) |
602 | Print(4095, " %d(%d)", proc, FindBlockID(tree->siblings[proc])); |
610 | Print(4095, " %d(%d)", proc, FindBlockID(tree->siblings[proc])); |
603 | Print(4095, "\n"); |
611 | Print(4095, "\n"); |
604 | } else { |
612 | } else { |
605 | if (tree->nprocs > 1) { |
613 | if (tree->nprocs > 1) { |
606 | Print(4095, " helping= "); |
614 | Print(4095, " helping= "); |
607 | for (proc = 0; proc < |
615 | for (proc = 0; proc < smp_max_threads; proc++) |
608 | if (tree->siblings[proc]) { |
616 | if (tree->siblings[proc]) { |
609 | if (proc == tree->thread_id) |
617 | if (proc == tree->thread_id) |
610 | Print(4095, "["); |
618 | Print(4095, "["); |
611 | Print(4095, "%d", proc); |
619 | Print(4095, "%d", proc); |
612 | if (proc == tree->thread_id) |
620 | if (proc == tree->thread_id) |
Line 616... | Line 624... | ||
616 | Print(4095, "\n"); |
624 | Print(4095, "\n"); |
617 | } |
625 | } |
618 | } |
626 | } |
619 | } |
627 | } |
620 | Unlock(lock_io); |
628 | Unlock(lock_io); |
621 | for (proc = 0; proc < |
629 | for (proc = 0; proc < smp_max_threads; proc++) |
622 | if (tree->siblings[proc]) |
630 | if (tree->siblings[proc]) |
623 | ThreadTrace(tree->siblings[proc], depth, brief); |
631 | ThreadTrace(tree->siblings[proc], depth, brief); |
624 | Unlock(tree->lock); |
632 | Unlock(tree->lock); |
625 | } |
633 | } |
626 | 634 | ||
627 | /* modified |
635 | /* modified 08/03/16 */ |
628 | /* |
636 | /* |
629 | ******************************************************************************* |
637 | ******************************************************************************* |
630 | * * |
638 | * * |
631 | * ThreadWait() is the idle loop for the N threads that are created at the * |
639 | * ThreadWait() is the idle loop for the N threads that are created at the * |
632 | * beginning when Crafty searches. Threads are "parked" here waiting on a * |
640 | * beginning when Crafty searches. Threads are "parked" here waiting on a * |
Line 667... | Line 675... | ||
667 | * falls through the while spin loop below because its * |
675 | * falls through the while spin loop below because its * |
668 | * "tree" pointer is already non-zero. * |
676 | * "tree" pointer is already non-zero. * |
669 | * * |
677 | * * |
670 | ************************************************************ |
678 | ************************************************************ |
671 | */ |
679 | */ |
672 | while ( |
680 | while (FOREVER) { |
673 | tstart = ReadClock(); |
681 | tstart = ReadClock(); |
674 | while (!thread[tid].tree && (!waiting || waiting->nprocs) && !Join(tid) && |
682 | while (!thread[tid].tree && (!waiting || waiting->nprocs) && !Join(tid) && |
675 | !thread[tid].terminate) |
683 | !thread[tid].terminate); |
676 | Pause(); |
- | |
677 | tend = ReadClock(); |
684 | tend = ReadClock(); |
678 | if (!thread[tid].tree) |
685 | if (!thread[tid].tree) |
679 | thread[tid].tree = waiting; |
686 | thread[tid].tree = waiting; |
680 | thread[tid].idle += tend - tstart; |
687 | thread[tid].idle += tend - tstart; |
681 | if (thread[tid].tree == waiting || thread[tid].terminate) |
688 | if (thread[tid].tree == waiting || thread[tid].terminate) |
Line 717... | Line 724... | ||
717 | tend = ReadClock(); |
724 | tend = ReadClock(); |
718 | thread[tid].idle += tend - tstart; |
725 | thread[tid].idle += tend - tstart; |
719 | } |
726 | } |
720 | } |
727 | } |
721 | 728 | ||
722 | /* modified |
729 | /* modified 08/03/16 */ |
723 | /* |
730 | /* |
724 | ******************************************************************************* |
731 | ******************************************************************************* |
725 | * * |
732 | * * |
726 | * CopyFromParent() is used to copy data from a parent thread to a child * |
733 | * CopyFromParent() is used to copy data from a parent thread to a child * |
727 | * thread. This only copies the appropriate parts of the TREE structure to * |
734 | * thread. This only copies the appropriate parts of the TREE structure to * |
Line 747... | Line 754... | ||
747 | child->position = parent->position; |
754 | child->position = parent->position; |
748 | for (i = 0; i <= rep_index + parent->ply; i++) |
755 | for (i = 0; i <= rep_index + parent->ply; i++) |
749 | child->rep_list[i] = parent->rep_list[i]; |
756 | child->rep_list[i] = parent->rep_list[i]; |
750 | for (i = ply - 1; i < MAXPLY; i++) |
757 | for (i = ply - 1; i < MAXPLY; i++) |
751 | child->killers[i] = parent->killers[i]; |
758 | child->killers[i] = parent->killers[i]; |
- | 759 | for (i = 0; i < 4096; i++) { |
|
- | 760 | child->counter_move[i] = parent->counter_move[i]; |
|
- | 761 | child->move_pair[i] = parent->move_pair[i]; |
|
- | 762 | } |
|
752 | for (i = ply - 1; i <= ply; i++) { |
763 | for (i = ply - 1; i <= ply; i++) { |
753 | child->curmv[i] = parent->curmv[i]; |
764 | child->curmv[i] = parent->curmv[i]; |
754 | child->pv[i] = parent->pv[i]; |
765 | child->pv[i] = parent->pv[i]; |
755 | } |
766 | } |
756 | child->in_check = parent->in_check; |
767 | child->in_check = parent->in_check; |
Line 781... | Line 792... | ||
781 | child->searched = parent->searched; |
792 | child->searched = parent->searched; |
782 | strcpy(child->root_move_text, parent->root_move_text); |
793 | strcpy(child->root_move_text, parent->root_move_text); |
783 | strcpy(child->remaining_moves_text, parent->remaining_moves_text); |
794 | strcpy(child->remaining_moves_text, parent->remaining_moves_text); |
784 | } |
795 | } |
785 | 796 | ||
786 | /* modified |
797 | /* modified 08/03/16 */ |
787 | /* |
798 | /* |
788 | ******************************************************************************* |
799 | ******************************************************************************* |
789 | * * |
800 | * * |
790 | * CopyToParent() is used to copy data from a child thread to a parent * |
801 | * CopyToParent() is used to copy data from a child thread to a parent * |
791 | * thread. This only copies the appropriate parts of the TREE structure to * |
802 | * thread. This only copies the appropriate parts of the TREE structure to * |
Line 826... | Line 837... | ||
826 | if (child->nodes_searched && !child->stop && value > parent->value && |
837 | if (child->nodes_searched && !child->stop && value > parent->value && |
827 | !abort_search) { |
838 | !abort_search) { |
828 | parent->pv[ply] = child->pv[ply]; |
839 | parent->pv[ply] = child->pv[ply]; |
829 | parent->value = value; |
840 | parent->value = value; |
830 | parent->cutmove = child->curmv[ply]; |
841 | parent->cutmove = child->curmv[ply]; |
- | 842 | for (i = 0; i < 4096; i++) { |
|
- | 843 | parent->counter_move[i] = child->counter_move[i]; |
|
- | 844 | parent->move_pair[i] = child->move_pair[i]; |
|
- | 845 | } |
|
831 | } |
846 | } |
832 | if (child->stop && ply == 1) |
847 | if (child->stop && ply == 1) |
833 | for (which = 0; which < n_root_moves; which++) |
848 | for (which = 0; which < n_root_moves; which++) |
834 | if (root_moves[which].move == child->curmv[ply]) { |
849 | if (root_moves[which].move == child->curmv[ply]) { |
835 | root_moves[which].status &= 7; |
850 | root_moves[which].status &= 7; |
Line 851... | Line 866... | ||
851 | } |
866 | } |
852 | which = FindBlockID(child) - 64 * child->thread_id - 1; |
867 | which = FindBlockID(child) - 64 * child->thread_id - 1; |
853 | Set(which, thread[child->thread_id].blocks); |
868 | Set(which, thread[child->thread_id].blocks); |
854 | } |
869 | } |
855 | 870 | ||
856 | /* modified |
871 | /* modified 08/03/16 */ |
857 | /* |
872 | /* |
858 | ******************************************************************************* |
873 | ******************************************************************************* |
859 | * * |
874 | * * |
860 | * GetBlock() is used to allocate a split block and fill in only SMP- * |
875 | * GetBlock() is used to allocate a split block and fill in only SMP- * |
861 | * critical information. The child process will copy the rest of the split * |
876 | * critical information. The child process will copy the rest of the split * |
Line 868... | Line 883... | ||
868 | * means no locks are needed until after the "joinable" flag is set, which * |
883 | * means no locks are needed until after the "joinable" flag is set, which * |
869 | * exposes this split point to other threads instantly. * |
884 | * exposes this split point to other threads instantly. * |
870 | * * |
885 | * * |
871 | ******************************************************************************* |
886 | ******************************************************************************* |
872 | */ |
887 | */ |
873 | TREE *GetBlock(TREE * |
888 | TREE *GetBlock(TREE * RESTRICT parent, int tid) { |
874 | TREE *child; |
889 | TREE *child; |
875 | static int warnings = 0; |
890 | static int warnings = 0; |
876 | int i, unused; |
891 | int i, unused; |
877 | /* |
892 | /* |
878 | ************************************************************ |
893 | ************************************************************ |
Line 927... | Line 942... | ||
927 | * of processors working here, etc, without any ugly race * |
942 | * of processors working here, etc, without any ugly race * |
928 | * conditions that would corrupt this critical data. * |
943 | * conditions that would corrupt this critical data. * |
929 | * * |
944 | * * |
930 | ************************************************************ |
945 | ************************************************************ |
931 | */ |
946 | */ |
932 | for (i = 0; i < |
947 | for (i = 0; i < smp_max_threads; i++) |
933 | child->siblings[i] = 0; |
948 | child->siblings[i] = 0; |
934 | child->nprocs = 0; |
949 | child->nprocs = 0; |
935 | child->stop = 0; |
950 | child->stop = 0; |
936 | child->joinable = 0; |
951 | child->joinable = 0; |
937 | child->joined = 0; |
952 | child->joined = 0; |
Line 952... | Line 967... | ||
952 | * invalid memory accesses and crash instantly. * |
967 | * invalid memory accesses and crash instantly. * |
953 | * * |
968 | * * |
954 | ******************************************************************************* |
969 | ******************************************************************************* |
955 | */ |
970 | */ |
956 | void WaitForAllThreadsInitialized(void) { |
971 | void WaitForAllThreadsInitialized(void) { |
957 | while (initialized_threads < |
972 | while (initialized_threads < smp_max_threads); /* Do nothing */ |
958 | } |
973 | } |
959 | 974 | ||
960 |
|
975 | #if !defined (UNIX) |
961 | /* modified |
976 | /* modified 08/03/16 */ |
962 | /* |
977 | /* |
963 | ******************************************************************************* |
978 | ******************************************************************************* |
964 | * * |
979 | * * |
965 | * ThreadMalloc() is called from the ThreadInit() function. It malloc's the * |
980 | * ThreadMalloc() is called from the ThreadInit() function. It malloc's the * |
966 | * split blocks in the local memory for the processor associated with the * |
981 | * split blocks in the local memory for the processor associated with the * |
Line 970... | Line 985... | ||
970 | */ |
985 | */ |
971 | extern void *WinMalloc(size_t, int); |
986 | extern void *WinMalloc(size_t, int); |
972 | void ThreadMalloc(int64_t tid) { |
987 | void ThreadMalloc(int64_t tid) { |
973 | int i; |
988 | int i; |
974 | 989 | ||
975 | for (i = |
990 | for (i = tid * 64 + 1; i < tid * 64 + 65; i++) { |
976 | if (block[i] == NULL) |
991 | if (block[i] == NULL) |
977 | block[i] = |
992 | block[i] = |
978 | (TREE *) ((~(size_t) 127) & (127 + (size_t) WinMalloc(sizeof(TREE) + |
993 | (TREE *) ((~(size_t) 127) & (127 + (size_t) WinMalloc(sizeof(TREE) + |
979 | 127, |
994 | 127, tid))); |
980 | block[i]->parent = NULL; |
995 | block[i]->parent = NULL; |
981 | LockInit(block[i]->lock); |
996 | LockInit(block[i]->lock); |
982 | } |
997 | } |
983 | } |
998 | } |
984 | # endif |
- | |
985 | #endif |
999 | #endif |