Skip to content

Commit e3e522a

Browse files
Merge branch 'main' into fix-pypi-link
2 parents 78b1599 + 9e0b590 commit e3e522a

File tree

4 files changed

+80
-2
lines changed

4 files changed

+80
-2
lines changed

runtime/nvqir/cutensornet/simulator_cutensornet.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ SimulatorTensorNetBase::SimulatorTensorNetBase()
2222
cudaq::mpi::is_initialized() ? cudaq::mpi::rank() % numDevices : 0;
2323
HANDLE_CUDA_ERROR(cudaSetDevice(deviceId));
2424
HANDLE_CUTN_ERROR(cutensornetCreate(&m_cutnHandle));
25+
// The scratch pad must be allocated after we have selected the device.
26+
scratchPad.allocate();
2527
}
2628

2729
static std::vector<std::complex<double>>

runtime/nvqir/cutensornet/tensornet_utils.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,12 @@ struct ScratchDeviceMem {
7272
2; // use half of available memory with alignment
7373
}
7474

75-
ScratchDeviceMem() {
75+
// Allocate scratch device memory based on available memory
76+
void allocate() {
77+
if (d_scratch)
78+
throw std::runtime_error(
79+
"Multiple scratch device memory allocations is not allowed.");
80+
7681
computeScratchSize();
7782
// Try allocate device memory
7883
auto errCode = cudaMalloc(&d_scratch, scratchSize);
@@ -86,7 +91,11 @@ struct ScratchDeviceMem {
8691
HANDLE_CUDA_ERROR(errCode);
8792
}
8893
}
89-
~ScratchDeviceMem() { HANDLE_CUDA_ERROR(cudaFree(d_scratch)); }
94+
95+
~ScratchDeviceMem() {
96+
if (scratchSize > 0)
97+
HANDLE_CUDA_ERROR(cudaFree(d_scratch));
98+
}
9099
};
91100

92101
/// Initialize `cutensornet` MPI Comm

unittests/CMakeLists.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,29 @@ if(TARGET nvqir-tensornet)
198198
message(STATUS "Building cutensornet backend tests.")
199199
create_tests_with_backend(tensornet "")
200200
create_tests_with_backend(tensornet-mps "")
201+
if (MPI_CXX_FOUND)
202+
# Count the number of GPUs
203+
find_program(NVIDIA_SMI "nvidia-smi")
204+
if(NVIDIA_SMI)
205+
execute_process(COMMAND bash -c "nvidia-smi --list-gpus | wc -l" OUTPUT_VARIABLE NGPUS)
206+
# Only build this test if we have more than 1 GPUs
207+
if (${NGPUS} GREATER_EQUAL 2)
208+
message(STATUS "Building cutensornet MPI tests.")
209+
add_executable(test_tensornet_mpi mpi/tensornet_mpi_tester.cpp)
210+
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE)
211+
target_link_options(test_tensornet_mpi PRIVATE -Wl,--no-as-needed)
212+
endif()
213+
target_link_libraries(test_tensornet_mpi
214+
PRIVATE
215+
cudaq
216+
cudaq-platform-default
217+
nvqir-tensornet
218+
gtest)
219+
add_test(NAME TensornetMPITest COMMAND ${MPIEXEC} --allow-run-as-root -np 2 ${CMAKE_BINARY_DIR}/unittests/test_tensornet_mpi)
220+
set_tests_properties(TensornetMPITest PROPERTIES LABELS "gpu_required;mgpus_required")
221+
endif() # NGPUS
222+
endif() # NVIDIA_SMI
223+
endif() # MPI_CXX_FOUND
201224
endif()
202225

203226
# Create an executable for SpinOp UnitTests
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. *
3+
* All rights reserved. *
4+
* *
5+
* This source code and the accompanying materials are made available under *
6+
* the terms of the Apache License 2.0 which accompanies this distribution. *
7+
******************************************************************************/
8+
#include <cudaq.h>
9+
#include <gtest/gtest.h>
10+
11+
TEST(TensornetMPITester, checkInit) {
12+
EXPECT_TRUE(cudaq::mpi::is_initialized());
13+
std::cout << "Rank = " << cudaq::mpi::rank() << "\n";
14+
}
15+
16+
TEST(TensornetMPITester, checkSimple) {
17+
constexpr std::size_t numQubits = 50;
18+
auto kernel = []() __qpu__ {
19+
cudaq::qvector q(numQubits);
20+
h(q[0]);
21+
for (int i = 0; i < numQubits - 1; i++)
22+
x<cudaq::ctrl>(q[i], q[i + 1]);
23+
mz(q);
24+
};
25+
26+
auto counts = cudaq::sample(100, kernel);
27+
28+
if (cudaq::mpi::rank() == 0) {
29+
EXPECT_EQ(2, counts.size());
30+
31+
for (auto &[bits, count] : counts) {
32+
printf("Observed: %s, %lu\n", bits.data(), count);
33+
EXPECT_EQ(numQubits, bits.size());
34+
}
35+
}
36+
}
37+
38+
int main(int argc, char **argv) {
39+
::testing::InitGoogleTest(&argc, argv);
40+
cudaq::mpi::initialize();
41+
const auto testResult = RUN_ALL_TESTS();
42+
cudaq::mpi::finalize();
43+
return testResult;
44+
}

0 commit comments

Comments
 (0)