prepare for new mlx / mlx-c release#227
Conversation
| let data = asDataCopy() | ||
| return data.data.withUnsafeBytes { ptr in | ||
| device.makeBuffer(bytes: ptr.baseAddress!, length: ptr.count) | ||
| } |
There was a problem hiding this comment.
Unrelated but per question the non-contiguous case wasn't actually making contiguous storage.
| /// specialized conversion between integer types -- see ``item(_:)`` | ||
| private func itemInt() -> Int { | ||
| precondition(self.size == 1) | ||
| eval() |
There was a problem hiding this comment.
Now includes an explicit eval in order to use the evalLock
| mlx_array_eval(ctx) | ||
| _ = evalLock.withLock { | ||
| mlx_array_eval(ctx) | ||
| } |
There was a problem hiding this comment.
All eval, asyncEval, Stream need to take a lock -- new version of mlx-c puts more work in the calling thread and it needs to be guarded. To be revisited in the future.
| outputShapes: [[Int]], | ||
| outputDTypes: [DType], | ||
| initValue: Float? = nil, | ||
| verbose: Bool = false |
| /// - stride: kernel stride | ||
| /// - padding: input padding | ||
| /// - dilation: kernel dilation | ||
| /// - outputPadding: output padding |
There was a problem hiding this comment.
The convTranspose functions pick up an outputPadding (optional)
| public func gatherMatmul( | ||
| _ a: MLXArray, _ b: MLXArray, lhsIndices: MLXArray? = nil, rhsIndices: MLXArray? = nil, | ||
| stream: StreamOrDevice = .default | ||
| sortedIndices: Bool = false, stream: StreamOrDevice = .default |
There was a problem hiding this comment.
gather_mm takes a hint for sorted indices
|
|
||
| deinit { | ||
| mlx_stream_free(ctx) | ||
| _ = evalLock.withLock { |
There was a problem hiding this comment.
Streams need to use the same lock as they manipulate the same shared structures.
| fatalError(message.map { String(cString: $0) } ?? "") | ||
| } | ||
|
|
||
| /// Evaluate the block with a scoped MLX error handler. |
There was a problem hiding this comment.
New error handling capabilities -- the import/export code requires this to correctly catch errors from mlx::core and this functionality is generally useful for swift code that wants to catch errors from core rather than fatally assert.
| /// | ||
| /// ### See Also | ||
| /// - ``exportFunctions(to:shapeless:_:export:)`` | ||
| /// - ``importFunction(from:)`` |
There was a problem hiding this comment.
New export/import capability -- the example code is from the tests.
Source/MLX/Ops.swift
Outdated
| mlx_load(&result, path.cString(using: .utf8), stream.ctx) | ||
| _ = try withError { | ||
| mlx_load(&result, path.cString(using: .utf8), stream.ctx) | ||
| } |
There was a problem hiding this comment.
These can properly catch an error for a missing file.
Note the _ = is because mlx_load returns an int
| /// | ||
| /// ### See Also | ||
| /// - <doc:lazy-evaluation> | ||
| public func checkedEval(_ values: Any...) throws { |
There was a problem hiding this comment.
For use when you want eval to throw. Note: this won't catch broadcasting errors as those occur at graph build time, e.g. a + b.
| public var eps: Double { | ||
| switch dtype { | ||
| case .float16: Double(Float16.ulpOfOne) | ||
| #if !arch(x86_64) |
There was a problem hiding this comment.
I ran into this when building apps that depended on it -- Float16 isn't a thing on x86. We don't see it in framework builds, but by default App builds do all architectures when building Release so we encounter this (even though that slice won't run)
There was a problem hiding this comment.
Right but presumably bfloat16 isn't a thing on x86 Macs as well. I guess the difference is we hardcode the bf16 values here.
but by default App builds do all architectures when building Release
I wonder how the rest of MLX builds in that case? I think MLX fp16 runs on x86 using the software implementation -- which means we should probably hardcode the values here too?
There was a problem hiding this comment.
BFloat isn't a type in swift so this one doesn't come up.
Sure, we could hard code the values here for x86 -- is that a supported configuration? Easy enough to do.
There was a problem hiding this comment.
is that a supported configuration?
I mean it's not common.. so this is kind of minor.
Linux x86 is supported and we run those tests regularly. macOS x86 is very uncommon.
Hence I also think it's fine to leave it like this and if anyone asks for that we can add it back.
Source/MLX/Export.swift
Outdated
| /// - url: file url to write the `.mlxfn` file | ||
| /// - shapeless: if `true` the function allows inputs with variable shapes | ||
| /// - f: the function to capture | ||
| /// - Returns: a help that records the call |
There was a problem hiding this comment.
The return comment there is unclear. What is a "help"?
There was a problem hiding this comment.
should be "helper" -- I will clarify
Source/MLX/Export.swift
Outdated
| /// - url: file url to write the `.mlxfn` file | ||
| /// - shapeless: if `true` the function allows inputs with variable shapes | ||
| /// - f: the function to capture | ||
| /// - export: closure for recording the calls |
There was a problem hiding this comment.
Looks like that parameter doesn't exist?
There was a problem hiding this comment.
Or maybe it's supposed to be a return?
There was a problem hiding this comment.
I guess I'm wrong about that.. but I'm trying to decipher how the export parameter works.
There was a problem hiding this comment.
try exportFunctions(to: url, shapeless: true, f) { export in
try export(x)
try export(x, x)
try export(x, x, x)
}
export is the trailing closure -- the { export in ... }
There was a problem hiding this comment.
and the export parameter in the closure is a FunctionExporterMultiple
There was a problem hiding this comment.
That's makes sense now.. but maybe is slightly confusing. Because the export parameter is both the closure and the name of the parameter to the closure. But if it's a common idiom then let's go for it.
There was a problem hiding this comment.
You don't normally see the name of the closure parameter (but you can). Let me think if there is a more expressive name. If not, I think nobody will notice as the trailing closure syntax is idiomatic.
Source/MLX/Export.swift
Outdated
| /// // f2 is a callable that represents the loaded function | ||
| /// let f2 = try importFunction(from: url) | ||
| /// | ||
| /// let a = MLXArray(10) | ||
| /// let b = MLXArray([5, 10, 20]) | ||
| /// | ||
| /// // call it -- the shapes and labels have to match | ||
| /// let r = try f2(a, y: b)[0] |
There was a problem hiding this comment.
Nit: name the function f rather than f2 as there is no f1
awni
left a comment
There was a problem hiding this comment.
Looks awesome. Left a few nits and some questions, please take a look. Otherwise I think this is good to go!
Thank you @awni -- appreciated as always! |
3cd0150 to
b057e39
Compare
- fixes #211 (moves metalKernel API back to what it was) - add improved swift error handling - add function import/export - adopt mlx v0.25.1 and mlx-c v0.2.0 - fixes #211 (moves metalKernel API back to what it was) - use an evalLock for eval, asyncEval and Stream creation - add withError and withErrorHandler error handling - add function import/export: https://ml-explore.github.io/mlx/build/html/usage/export.html
b057e39 to
7874c5a
Compare
Uh oh!
There was an error while loading. Please reload this page.