| 713 | } |
| 714 | |
| 715 | int DeviceManager::setActiveDevice(int device, int nId) { |
| 716 | thread_local bool retryFlag = true; |
| 717 | |
| 718 | int numDevices = cuDevices.size(); |
| 719 | |
| 720 | if (device >= numDevices) { return -1; } |
| 721 | |
| 722 | int old = getActiveDeviceId(); |
| 723 | |
| 724 | if (nId == -1) { nId = getDeviceNativeId(device); } |
| 725 | |
| 726 | cudaError_t err = cudaSetDevice(nId); |
| 727 | |
| 728 | if (err == cudaSuccess) { |
| 729 | tlocalActiveDeviceId() = device; |
| 730 | return old; |
| 731 | } |
| 732 | |
| 733 | // For the first time a thread calls setDevice, |
| 734 | // if the requested device is unavailable, try checking |
| 735 | // for other available devices - while loop below |
| 736 | if (!retryFlag) { |
| 737 | CUDA_CHECK(err); |
| 738 | return old; |
| 739 | } |
| 740 | |
| 741 | // Comes only when retryFlag is true. Set it to false |
| 742 | retryFlag = false; |
| 743 | |
| 744 | while (true) { |
| 745 | // Check for errors other than DevicesUnavailable |
| 746 | // If success, return. Else throw error |
| 747 | // If DevicesUnavailable, try other devices (while loop below) |
| 748 | if (err != cudaErrorDeviceAlreadyInUse) { |
| 749 | CUDA_CHECK(err); |
| 750 | tlocalActiveDeviceId() = device; |
| 751 | return old; |
| 752 | } |
| 753 | cudaGetLastError(); // Reset error stack |
| 754 | #ifndef NDEBUG |
| 755 | getLogger()->warn( |
| 756 | "Warning: Device {} is unavailable. Using next available " |
| 757 | "device \n", |
| 758 | device); |
| 759 | #endif |
| 760 | // Comes here is the device is in exclusive mode or |
| 761 | // otherwise fails streamCreate with this error. |
| 762 | // All other errors will error out |
| 763 | device++; |
| 764 | if (device >= numDevices) { break; } |
| 765 | |
| 766 | // Can't call getNativeId here as it will cause an infinite loop with |
| 767 | // the constructor |
| 768 | nId = cuDevices[device].nativeId; |
| 769 | |
| 770 | err = cudaSetDevice(nId); |
| 771 | } |
| 772 |
no test coverage detected