Skip to content

Commit cd5120c

Browse files
implemented cross-platform RAM probe (#636)
Mai (Roll249) implemented the probe, and Tyson updated the tests and authorlist --------- Co-authored-by: Tyson Jones <[email protected]>
1 parent 8678836 commit cd5120c

File tree

6 files changed

+91
-17
lines changed

6 files changed

+91
-17
lines changed

AUTHORS.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ Dr Ian Bush [consultant]
4444
HPC
4545

4646
External contributors:
47+
Mai Đức Khang
48+
implemented RAM probe (for unitaryHACK issue #600)
4749
James Richings
4850
patched overflow in bitwise.hpp logic
4951
Luc Jaulmes

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ See the [docs](docs/README.md) for enabling acceleration and running the unit te
257257

258258
In addition to QuEST's [authors](AUTHORS.txt), we sincerely thank the following external contributors to QuEST.
259259

260+
- [Mai Đức Khang](https://github.com/Roll249) for implementing a RAM probe (unitaryHACK 2025 [#600](https://github.com/QuEST-Kit/QuEST/issues/600)).
260261
- [James Richings](https://github.com/JPRichings) for patching a v4 overflow bug.
261262
- [Luc Jaulmes](https://github.com/lucjaulmes) for patching v4's CMake installation.
262263
- [Jakub Adamski](https://github.com/jjacobx) for optimising distributed communication of max-size messages.

quest/src/core/memory.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@
2121

2222
#include <cstdlib>
2323

24+
// Platform-specific includes for RAM querying
25+
#if defined(__linux__)
26+
#include <sys/sysinfo.h>
27+
#elif defined(__APPLE__)
28+
#include <sys/types.h>
29+
#include <sys/sysctl.h>
30+
#elif defined(_WIN32)
31+
#define NOMINMAX
32+
#include <windows.h>
33+
#endif
34+
2435

2536

2637
/*
@@ -196,11 +207,23 @@ qindex mem_getMaxNumKrausMapMatricesBeforeLocalMemSizeofOverflow(int numQubits)
196207

197208

198209
qindex mem_tryGetLocalRamCapacityInBytes() {
199-
200-
/// @todo attempt to find total Ram
201-
202-
// if we're unable to find total RAM, throw an exception
203-
// (which the caller should catch and gracefully continue)
210+
#if defined(__linux__)
211+
struct sysinfo info;
212+
if (sysinfo(&info) == 0)
213+
return (qindex) info.totalram * info.mem_unit;
214+
#elif defined(__APPLE__)
215+
int mib[2] = {CTL_HW, HW_MEMSIZE};
216+
int64_t memsize = 0;
217+
size_t len = sizeof(memsize);
218+
if (sysctl(mib, 2, &memsize, &len, NULL, 0) == 0 && memsize > 0)
219+
return (qindex) memsize;
220+
#elif defined(_WIN32)
221+
MEMORYSTATUSEX statex;
222+
statex.dwLength = sizeof(statex);
223+
if (GlobalMemoryStatusEx(&statex))
224+
return (qindex) statex.ullTotalPhys;
225+
#endif
226+
// fallback: throw exception
204227
throw (mem::COULD_NOT_QUERY_RAM) false;
205228
}
206229

tests/unit/channels.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,11 @@ TEST_CASE( "createKrausMap", TEST_CATEGORY ) {
126126
// GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
127127
// advance or whether it proceeded to malloc() which subsequently failed
128128
#ifndef SANITIZER_IS_ACTIVE
129-
REQUIRE_THROWS_WITH( createKrausMap(12,1), ContainsSubstring("failed") || ContainsSubstring("insufficient available memory") || ContainsSubstring("available GPU memory") );
129+
REQUIRE_THROWS_WITH( createKrausMap(12,1),
130+
ContainsSubstring("failed") ||
131+
ContainsSubstring("insufficient available memory") ||
132+
ContainsSubstring("exceeds the available memory") ||
133+
ContainsSubstring("available GPU memory") );
130134
#endif
131135
}
132136

@@ -512,7 +516,11 @@ TEST_CASE( "createSuperOp", TEST_CATEGORY ) {
512516
// GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
513517
// advance or whether it proceeded to malloc() which subsequently failed
514518
#ifndef SANITIZER_IS_ACTIVE
515-
REQUIRE_THROWS_WITH( createSuperOp(12), ContainsSubstring("failed") || ContainsSubstring("insufficient available memory") || ContainsSubstring("available GPU memory") );
519+
REQUIRE_THROWS_WITH( createSuperOp(12),
520+
ContainsSubstring("failed") ||
521+
ContainsSubstring("insufficient available memory") ||
522+
ContainsSubstring("available GPU memory") ||
523+
ContainsSubstring("exceeds that available") );
516524
#endif
517525
}
518526
}

tests/unit/matrices.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,11 @@ TEST_CASE( "createCompMatr", TEST_CATEGORY ) {
456456
// GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
457457
// advance or whether it proceeded to malloc() which subsequently failed
458458
#ifndef SANITIZER_IS_ACTIVE
459-
REQUIRE_THROWS_WITH( createCompMatr(25), ContainsSubstring("failed") || ContainsSubstring("insufficient available memory") || ContainsSubstring("available GPU memory") );
459+
REQUIRE_THROWS_WITH( createCompMatr(25),
460+
ContainsSubstring("failed") ||
461+
ContainsSubstring("insufficient available memory") ||
462+
ContainsSubstring("available GPU memory") ||
463+
ContainsSubstring("exceeds the available RAM") );
460464
#endif
461465
}
462466
}
@@ -529,7 +533,11 @@ TEST_CASE( "createDiagMatr", TEST_CATEGORY ) {
529533
// GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
530534
// advance or whether it proceeded to malloc() which subsequently failed
531535
#ifndef SANITIZER_IS_ACTIVE
532-
REQUIRE_THROWS_WITH( createDiagMatr(50), ContainsSubstring("failed") || ContainsSubstring("insufficient available memory") || ContainsSubstring("available GPU memory") );
536+
REQUIRE_THROWS_WITH( createDiagMatr(50),
537+
ContainsSubstring("failed") ||
538+
ContainsSubstring("insufficient available memory") ||
539+
ContainsSubstring("available GPU memory") ||
540+
ContainsSubstring("exceeds the available RAM") );
533541
#endif
534542
}
535543
}
@@ -602,7 +610,11 @@ TEST_CASE( "createFullStateDiagMatr", TEST_CATEGORY ) {
602610
// GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
603611
// advance or whether it proceeded to malloc() which subsequently failed
604612
#ifndef SANITIZER_IS_ACTIVE
605-
REQUIRE_THROWS_WITH( createFullStateDiagMatr(50), ContainsSubstring("failed") || ContainsSubstring("insufficient available memory") || ContainsSubstring("available GPU memory") );
613+
REQUIRE_THROWS_WITH( createFullStateDiagMatr(50),
614+
ContainsSubstring("failed") ||
615+
ContainsSubstring("insufficient available memory") ||
616+
ContainsSubstring("available GPU memory") ||
617+
ContainsSubstring("exceeds the available RAM") );
606618
#endif
607619
}
608620

@@ -698,7 +710,11 @@ TEST_CASE( "createCustomFullStateDiagMatr", TEST_CATEGORY ) {
698710
// GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
699711
// advance or whether it proceeded to malloc() which subsequently failed
700712
#ifndef SANITIZER_IS_ACTIVE
701-
REQUIRE_THROWS_WITH( createCustomFullStateDiagMatr(50, mpi,gpu,omp), ContainsSubstring("failed") || ContainsSubstring("insufficient available memory") || ContainsSubstring("available GPU memory") );
713+
REQUIRE_THROWS_WITH( createCustomFullStateDiagMatr(50, mpi,gpu,omp),
714+
ContainsSubstring("failed") ||
715+
ContainsSubstring("insufficient available memory") ||
716+
ContainsSubstring("available GPU memory") ||
717+
ContainsSubstring("exceeds the available RAM") );
702718
#endif
703719
}
704720
}

tests/unit/qureg.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,11 @@ TEST_CASE( "createQureg", TEST_CATEGORY ) {
125125
// GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
126126
// advance or whether it proceeded to malloc() which subsequently failed
127127
#ifndef SANITIZER_IS_ACTIVE
128-
REQUIRE_THROWS_WITH( createQureg(50), ContainsSubstring("failed") || ContainsSubstring("insufficient available memory") || ContainsSubstring("available GPU memory") );
128+
REQUIRE_THROWS_WITH( createQureg(50),
129+
ContainsSubstring("failed") ||
130+
ContainsSubstring("insufficient available memory") ||
131+
ContainsSubstring("available GPU memory") ||
132+
ContainsSubstring("RAM") );
129133
#endif
130134
}
131135
}
@@ -210,7 +214,11 @@ TEST_CASE( "createDensityQureg", TEST_CATEGORY ) {
210214
// GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
211215
// advance or whether it proceeded to malloc() which subsequently failed
212216
#ifndef SANITIZER_IS_ACTIVE
213-
REQUIRE_THROWS_WITH( createDensityQureg(25), ContainsSubstring("failed") || ContainsSubstring("insufficient available memory") || ContainsSubstring("available GPU memory") );
217+
REQUIRE_THROWS_WITH( createDensityQureg(25),
218+
ContainsSubstring("failed") ||
219+
ContainsSubstring("insufficient available memory") ||
220+
ContainsSubstring("available GPU memory") ||
221+
ContainsSubstring("RAM") );
214222
#endif
215223
}
216224
}
@@ -302,7 +310,11 @@ TEST_CASE( "createForcedQureg", TEST_CATEGORY ) {
302310
// GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
303311
// advance or whether it proceeded to malloc() which subsequently failed
304312
#ifndef SANITIZER_IS_ACTIVE
305-
REQUIRE_THROWS_WITH( createForcedQureg(50), ContainsSubstring("failed") || ContainsSubstring("insufficient available memory") || ContainsSubstring("available GPU memory") );
313+
REQUIRE_THROWS_WITH( createForcedQureg(50),
314+
ContainsSubstring("failed") ||
315+
ContainsSubstring("insufficient available memory") ||
316+
ContainsSubstring("available GPU memory") ||
317+
ContainsSubstring("RAM") );
306318
#endif
307319
}
308320
}
@@ -395,7 +407,11 @@ TEST_CASE( "createForcedDensityQureg", TEST_CATEGORY ) {
395407
// GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
396408
// advance or whether it proceeded to malloc() which subsequently failed
397409
#ifndef SANITIZER_IS_ACTIVE
398-
REQUIRE_THROWS_WITH( createForcedDensityQureg(25), ContainsSubstring("failed") || ContainsSubstring("insufficient available memory") || ContainsSubstring("available GPU memory") );
410+
REQUIRE_THROWS_WITH( createForcedDensityQureg(25),
411+
ContainsSubstring("failed") ||
412+
ContainsSubstring("insufficient available memory") ||
413+
ContainsSubstring("available GPU memory") ||
414+
ContainsSubstring("RAM") );
399415
#endif
400416
}
401417
}
@@ -531,8 +547,16 @@ TEST_CASE( "createCustomQureg", TEST_CATEGORY ) {
531547
// GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
532548
// advance or whether it proceeded to malloc() which subsequently failed
533549
#ifndef SANITIZER_IS_ACTIVE
534-
REQUIRE_THROWS_WITH( createCustomQureg(50, 0, 0,0,0), ContainsSubstring("failed") || ContainsSubstring("insufficient available memory") || ContainsSubstring("available GPU memory") );
535-
REQUIRE_THROWS_WITH( createCustomQureg(25, 1, 0,0,0), ContainsSubstring("failed") || ContainsSubstring("insufficient available memory") || ContainsSubstring("available GPU memory") );
550+
REQUIRE_THROWS_WITH( createCustomQureg(50, 0, 0,0,0),
551+
ContainsSubstring("failed") ||
552+
ContainsSubstring("insufficient available memory") ||
553+
ContainsSubstring("available GPU memory") ||
554+
ContainsSubstring("RAM") );
555+
REQUIRE_THROWS_WITH( createCustomQureg(25, 1, 0,0,0),
556+
ContainsSubstring("failed") ||
557+
ContainsSubstring("insufficient available memory") ||
558+
ContainsSubstring("available GPU memory") ||
559+
ContainsSubstring("RAM") );
536560
#endif
537561
}
538562
}

0 commit comments

Comments
 (0)