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 |