Describe the bug
On cpu-only Linux machine, I discover that mlx c++ uses cpu device, but mlx-swift uses gpu backend which is unavailable.
- The method
Device.setDefault is deprecated, but without it, the default device is still gpu.
- The method
Device.withDefaultDevice is not working on Linux.
- MLXFast and others targets can not build on Linux.
- Both main branch and 0.10.0 version have the bug.
To Reproduce
Include code snippet
- Create a package with executable.
// swift-tools-version: 6.3
import PackageDescription
let package = Package(
name: "mlx_remote_test",
dependencies: [
.package(url: "https://github.com/ml-explore/mlx-swift", from: "0.10.0")
],
targets: [
.executableTarget(
name: "mlx_remote_test",
dependencies: [
.product(name: "MLX", package: "mlx-swift")
]
)
],
swiftLanguageModes: [.v6]
)
@main
struct mlx_remote_test {
static func main() {
Device.withDefaultDevice(.cpu, {
let x = MLXArray.ones([2, 3])
let y = MLXArray(10.0)
let z = x + y
let meanValue = z.mean()
MLX.eval(z, meanValue)
print("x shape: \(x.shape)")
print("y: \(y)")
print("z = x + y:\n\(z)")
print("mean(z): \(meanValue)")
})
}
}
Expected behavior
- mlx-c have some methods to check gpu or cpu.
Device.withDefaultDevice should change device.
Desktop:
- OS Version: Linux 6.8.0-87-generic 88~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC x86_64 x86_64 x86_64 GNU/Linux
- Device: A cheap Asus laptop without GPU.
- Version: 6.8.0-87-generic
Additional context
One possible fix to change default device.
private static func _resolveGlobalDefaultDevice() -> Device {
_lock.withLock {
- _defaultDevice ?? .gpu
+ if let device = _defaultDevice {
+ return device
+ }
+ var ctx = mlx_device_new()
+ mlx_get_default_device(&ctx)
+ return Device(ctx)
}
}
Recently I modified mlx-swift to expose MLX C++ by moving mlx C++ to a new target MLXCxx, maybe a good pull request?
Some related directories to move:
- Move mlx c++ submodule to
Source/MLXCxx
Source/Cmlx/fmt -> Source/MLXCxx/fmt
Source/Cmlx/json -> Source/MLXCxx/json
Source/Cmlx/metal-cpp -> Source/MLXCxx/metal-cpp
Source/Cmlx/mlx -> Source/MLXCxx/mlx
Source/Cmlx/mlx-generated -> Source/MLXCxx/mlx-generated
Source/Cmlx/mlx-conditional -> Source/MLXCxx/mlx-conditional
New Target:
let mlxcxx = Target.target(
name: "MLXCxx",
path: "Source/MLXCxx",
exclude: platformExcludes + [...],
publicHeadersPath: "mlx",
cSettings: [
.headerSearchPath("mlx"),
],
cxxSettings: cxxSettings + [
.headerSearchPath("mlx"),
.headerSearchPath("json/single_include/nlohmann"),
.headerSearchPath("fmt/include"),
.define("SWIFTPM_BUNDLE", to: "\"mlx-swift_MLXCxx\""),
.define("MLX_VERSION", to: "\"0.31.1\""),
],
linkerSettings: linkerSettings
)
Describe the bug
On cpu-only Linux machine, I discover that mlx c++ uses cpu device, but mlx-swift uses gpu backend which is unavailable.
Device.setDefaultis deprecated, but without it, the default device is still gpu.Device.withDefaultDeviceis not working on Linux.To Reproduce
Include code snippet
Expected behavior
Device.withDefaultDeviceshould change device.Desktop:
Additional context
One possible fix to change default device.
private static func _resolveGlobalDefaultDevice() -> Device { _lock.withLock { - _defaultDevice ?? .gpu + if let device = _defaultDevice { + return device + } + var ctx = mlx_device_new() + mlx_get_default_device(&ctx) + return Device(ctx) } }Recently I modified mlx-swift to expose MLX C++ by moving mlx C++ to a new target
MLXCxx, maybe a good pull request?Some related directories to move:
Source/MLXCxxSource/Cmlx/fmt->Source/MLXCxx/fmtSource/Cmlx/json->Source/MLXCxx/jsonSource/Cmlx/metal-cpp->Source/MLXCxx/metal-cppSource/Cmlx/mlx->Source/MLXCxx/mlxSource/Cmlx/mlx-generated->Source/MLXCxx/mlx-generatedSource/Cmlx/mlx-conditional->Source/MLXCxx/mlx-conditionalNew Target: