Repository navigation
GPU.deviceInfo(): select the device like MLX, without the window server - #498
Merged
davidkoski merged 1 commit intoOct 20, 2026
Merged
Conversation
GPU.deviceInfo() called MTLCreateSystemDefaultDevice() on every call. In a command-line process the first such call opens a window server session (SLSCreateDefaultMetalDevice -> SLSMainDisplayID -> SLSInitialize -> CGSDisplayInitialize). That step can stall for many seconds. Select the device the same way as metal::load_device in MLX: the first device of MTLCopyAllDevices(), else MTLCreateSystemDefaultDevice(). Compute the value once per process. The public API and the returned fields do not change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
davidkoski
reviewed
Oct 15, 2026
| // device of MTLCopyAllDevices(), else the system default device. In a | ||
| // command-line process MTLCreateSystemDefaultDevice() opens a window | ||
| // server session, which can stall for several seconds. | ||
| #if os(macOS) |
Member
There was a problem hiding this comment.
You might also want to cover macCatalyst here too -- the same calls are available but it isn't os(macOS):
#if os(macOS) || targetEnvironment(macCatalyst)Though if the primary concern is for command line tools, I am not sure you can create one that is macCatalyst.
davidkoski
requested changes
Oct 15, 2026
davidkoski
left a comment
Member
There was a problem hiding this comment.
Change looks good, but see comment on macCatalyst -- change that or let me know if you think it isn't needed.
Thank you!
Member
|
I am going to merge as-is -- the macCatalyst change can be made as another PR if needed, but given how those binaries work it may not be a useful case. |
davidkoski
approved these changes
Oct 20, 2026
8 of 9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed changes
GPU.deviceInfo()callsMTLCreateSystemDefaultDevice()on every call. In a command-line process (not an app bundle), the first such call opens a window server session. That step can stall for many seconds.A
sampleof a stalled process shows this stack:In the unified log, the process logs
TCCAccessRequestforkTCCServiceListenEventand acom.apple.SkyLightsession line, and then nothing until the call returns. On an M5 Max, over 25 runs of the same command-line process, the gap from that SkyLight line to the next event was 0.35 to 0.89 s in 23 runs, 7.1 s once and 30.1 s once. In our case the call happened inside a timed step, so the 30 s stall failed the run.MLX itself does not use the window server to pick its device.
metal::load_device(mlx/backend/metal/device.cpp) takes the first device ofMTL::CopyAllDevices()and usesMTL::CreateSystemDefaultDevice()only when that list is empty.This PR:
metal::load_device:MTLCopyAllDevices().first, elseMTLCreateSystemDefaultDevice().MTLCopyAllDevicesis macOS-only, so other platforms keepMTLCreateSystemDefaultDevice().private static let). The device properties it reads (architecture,maxBufferLength,recommendedMaxWorkingSetSize,HW_MEMSIZE) do not change while the process runs.Testing
MemoryTests.testDeviceInfo: on a GPU device,deviceInfo()reports a real architecture, a nonzero buffer size and working set size, and a second call returns the same values.xcodebuild build-for-testing -scheme mlx-swift-Package -destination 'platform=macOS', thenxctestforCmlxTests(1 passed),MLXTests(385 executed, 2 skipped, 0 failures) andMLXIntegrationTests(669 passed).xcodebuild build -scheme mlx-swift-Package -destination 'generic/platform=iOS'succeeds.MTLCopyAllDevices().firstandMTLCreateSystemDefaultDevice()return the same device, architecture,maxBufferLengthandrecommendedMaxWorkingSetSize. The unified log for theMTLCopyAllDevicespath has no TCC or SkyLight lines. TheMTLCreateSystemDefaultDevicepath logsTCCAccessRequest(kTCCServiceListenEvent)and a SkyLight session.Checklist
Put an
xin the boxes that apply.pre-commit run --all-filesto format my code / installed pre-commit prior to committing changes🤖 Generated with Claude Code