Skip to content

Commit 00116a7

Browse files
committed
GPU Metal: size the automatic grids by the number of GPU cores
The multiprocessor count, of which the automatically sized grids launch minBlocks blocks each, was never set and stayed 1, so those kernels ran one or a few threadgroups on a 32-core M1 Max. Metal does not report the core count; read gpu-core-count from the GPU's IORegistry entry, as CUDA uses multiProcessorCount, and link IOKit for that.
1 parent e88b598 commit 00116a7

2 files changed

Lines changed: 32 additions & 1 deletion

File tree

‎GPU/GPUTracking/Base/metal/CMakeLists.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2")
4646
PUBLIC_LINK_LIBRARIES O2::GPUTracking
4747
TARGETVARNAME targetName)
4848

49-
target_link_libraries(${targetName} PUBLIC ${METAL_FRAMEWORKS})
49+
target_link_libraries(${targetName} PUBLIC ${METAL_FRAMEWORKS} "-framework IOKit")
5050

5151
target_compile_definitions(${targetName} PRIVATE $<TARGET_PROPERTY:O2::GPUTracking,COMPILE_DEFINITIONS>)
5252
# the compile_defitions are not propagated automatically on purpose (they are

‎GPU/GPUTracking/Base/metal/GPUReconstructionMetal.mm‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <cstddef>
1919
#include <map>
2020

21+
#include <IOKit/IOKitLib.h>
2122
#include <mach-o/dyld.h>
2223
#include <mach-o/getsect.h>
2324
#include <mach-o/ldsyms.h> // _mh_execute_header
@@ -28,6 +29,28 @@
2829
return (1); \
2930
}
3031

32+
namespace
33+
{
34+
// Metal does not report the number of GPU cores, but the IORegistry entry of
35+
// an Apple silicon GPU does. 0 if it is not there.
36+
uint32_t metalGPUCoreCount()
37+
{
38+
uint32_t n = 0;
39+
io_service_t service = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("AGXAccelerator"));
40+
if (service) {
41+
CFTypeRef p = IORegistryEntrySearchCFProperty(service, kIOServicePlane, CFSTR("gpu-core-count"), kCFAllocatorDefault, kIORegistryIterateRecursively);
42+
if (p) {
43+
if (CFGetTypeID(p) == CFNumberGetTypeID()) {
44+
CFNumberGetValue((CFNumberRef)p, kCFNumberSInt32Type, &n);
45+
}
46+
CFRelease(p);
47+
}
48+
IOObjectRelease(service);
49+
}
50+
return n;
51+
}
52+
} // namespace
53+
3154
#include "utils/qGetLdBinarySymbols.h"
3255
QGET_LD_BINARY_SYMBOLS(GPUReconstructionMetalCode_src);
3356

@@ -74,6 +97,14 @@
7497
mDeviceName = device_name.c_str();
7598
// Basically a random number for now.
7699
mMaxBackendThreads = 1000;
100+
// The automatic grids are minBlocks per core; with the default of 1 they
101+
// left all but one core idle.
102+
mMultiprocessorCount = metalGPUCoreCount();
103+
if (mMultiprocessorCount == 0) {
104+
GPUWarning("Could not read the number of GPU cores, assuming 1");
105+
mMultiprocessorCount = 1;
106+
}
107+
mMaxBackendThreads = std::max<int32_t>(mMaxBackendThreads, deviceMaxWorkGroup.width * mMultiprocessorCount);
77108

78109
if (GetMetalPrograms()) {
79110
return 1;

0 commit comments

Comments
 (0)