| 1657 | } |
| 1658 | |
| 1659 | void assertQuregFitsInGpuMem(int numQubits, int isDensMatr, int isDistrib, int isGpuAccel, QuESTEnv env, const char* caller) { |
| 1660 | |
| 1661 | // validate when GPU-acceleration is possible; EVEN if it's auto! Because the auto-deployer will never |
| 1662 | // fall-back to painfully slow CPU if the GPU memory is filled. So if GPU-accel is possible, it must fit qureg. |
| 1663 | if (isGpuAccel == 0 || env.isGpuAccelerated == 0) |
| 1664 | return; |
| 1665 | |
| 1666 | // we consult the current available local GPU memory (being more strict than is possible for RAM) |
| 1667 | size_t localCurrGpuMem = gpu_getCurrentAvailableMemoryInBytes(); |
| 1668 | |
| 1669 | // check whether qureg (considering if distributed) fits between node GPU memory(s). |
| 1670 | // note this sets numQuregNodes=1 only when distribution is impossible/switched-off, |
| 1671 | // but not when it would later be automatically disabled. that's fine; the auto-deployer |
| 1672 | // will never disable distribution if local GPU memory can't store the qureg, so we don't |
| 1673 | // need to validate the auto-deployed-to-non-distributed scenario. we only need to ensure |
| 1674 | // that auto-deploying-to-distribution is permitted by GPU memory capacity. |
| 1675 | int numQuregNodes = (isDistrib == 0 || ! env.isDistributed)? 1 : env.numNodes; |
| 1676 | bool quregFitsInMem = mem_canQuregFitInMemory(numQubits, isDensMatr, numQuregNodes, localCurrGpuMem); |
| 1677 | |
| 1678 | tokenSubs vars = { |
| 1679 | {"${IS_DENS}", isDensMatr}, |
| 1680 | {"${NUM_QUBITS}", numQubits}, |
| 1681 | {"${QCOMP_BYTES}", sizeof(qcomp)}, |
| 1682 | {"${MIN_VRAM_AVAIL}", localCurrGpuMem}}; |
| 1683 | |
| 1684 | // make error message specific to whether qureg is local or distributed |
| 1685 | if (numQuregNodes == 1) { |
| 1686 | vars["${EXP_BASE}"] = (isDensMatr)? 4 : 2; |
| 1687 | |
| 1688 | // require expensive node consensus in case of heterogeneous GPU hardware or loads |
| 1689 | assertAllNodesAgreeThat(quregFitsInMem, report::NEW_QUREG_CANNOT_FIT_INTO_NON_DISTRIB_CURRENT_GPU_MEM, vars, caller); |
| 1690 | |
| 1691 | // when distributed, comm buffers are considered (hence +1 below) |
| 1692 | } else { |
| 1693 | vars["${LOG2_NUM_AMPS}"] = 1 + mem_getEffectiveNumStateVecQubitsPerNode(numQubits, isDensMatr, numQuregNodes); |
| 1694 | vars["${NUM_GPUS}"] = numQuregNodes; |
| 1695 | |
| 1696 | // require expensive node consensus in case of heterogeneous GPU hardware or loads |
| 1697 | assertAllNodesAgreeThat(quregFitsInMem, report::NEW_QUREG_CANNOT_FIT_INTO_POTENTIALLY_DISTRIB_CURRENT_GPU_MEM, vars, caller); |
| 1698 | } |
| 1699 | } |
| 1700 | |
| 1701 | void validate_newQuregParams(int numQubits, int isDensMatr, int isDistrib, int isGpuAccel, int isMultithread, QuESTEnv env, const char* caller) { |
| 1702 |
no test coverage detected