Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bind MetalPerformanceShadersGraph Framework #14286

Closed
praeclarum opened this issue Mar 1, 2022 · 6 comments · Fixed by #14303
Closed

Bind MetalPerformanceShadersGraph Framework #14286

praeclarum opened this issue Mar 1, 2022 · 6 comments · Fixed by #14303
Labels
feature A feature to be implemented
Milestone

Comments

@praeclarum
Copy link
Contributor

praeclarum commented Mar 1, 2022

Apple has introduced yet another neural network library. :-) It's been around since iOS 14 and works on Mac/MacCat/TV also.

This one is pretty great though. It has a lot more features than MPSNNGraph and is a lot easier to use. It also looks pretty easy to bind. There are the main types MPSGraph, MPSGraphTensor, and MPSGraphTensorData and the rest is just a giant set of functions on MPSGraph (a few structs and enums too).

https://github.com/xamarin/xamarin-macios/blob/dfe6c2b5ab472a522240648e2556641efd586ec8/tests/xtro-sharpie/iOS-MetalPerformanceShadersGraph.todo

Apple has an example here: https://developer.apple.com/documentation/metalperformanceshadersgraph/training_a_neural_network_using_mps_graph?language=objc

Looks like they expect users to subclass MPSGraph so we need to make sure that's possible.

I'm willing to do the work... if I can remember how. I'd love for this to get into dotnet 6.

Steps to Reproduce

  1. Try to use the MetalPerformanceShadersGraph Framework

Expected Behavior

The API is fully bound.

Actual Behavior

Nothing is bound currently.

Environment

=== Visual Studio Enterprise 2019 for Mac ===

Version 8.10.14 (build 17)
Installation UUID: c4618a09-6326-4305-9dd0-997046eecbae
	GTK+ 2.24.23 (Raleigh theme)
	Xamarin.Mac 6.18.0.23 (d16-6 / 088c73638)

	Package version: 612000171

=== Mono Framework MDK ===

Runtime:
	Mono 6.12.0.171 (2020-02/4efc825e831) (64-bit)
	Package version: 612000171

=== Roslyn (Language Service) ===

3.10.0-4.21269.26+029847714208ebe49668667c60ea5b0a294e0fcb

=== NuGet ===

Version: 5.9.0.7134

=== .NET Core SDK ===

SDK: /usr/local/share/dotnet/sdk/6.0.101/Sdks
SDK Versions:
	6.0.101
	6.0.100
	5.0.404
	5.0.403
	5.0.302
	5.0.203
	5.0.202
	5.0.201
	5.0.102
	5.0.100
	3.1.416
	3.1.415
	3.1.411
	3.1.409
	3.1.408
	3.1.407
	3.1.405
	3.1.403
	3.1.402
	3.1.300
	3.1.200
	3.1.102
	3.1.101
	3.1.100
	3.0.100
	2.2.203
	2.2.103
	2.1.302
	2.0.3
MSBuild SDKs: /Applications/Visual Studio.app/Contents/Resources/lib/monodevelop/bin/MSBuild/Current/bin/Sdks

=== .NET Core Runtime ===

Runtime: /usr/local/share/dotnet/dotnet
Runtime Versions:
	6.0.1
	6.0.0
	5.0.13
	5.0.12
	3.1.22
	3.1.21

=== .NET Core 3.1 SDK ===

SDK: 3.1.416

=== Xamarin.Profiler ===

Version: 1.7.0.0
Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler

=== Updater ===

Version: 11

=== Xamarin Designer ===

Version: 16.11.0.39
Hash: cd672761d
Branch: remotes/origin/d16-11
Build date: 2021-10-06 21:09:18 UTC

=== Apple Developer Tools ===

Xcode 13.2.1 (19586)
Build 13C100

=== Xamarin.Mac ===

Version: 8.5.0.5 (Visual Studio Enterprise)
Hash: e49c11f99
Branch: main
Build date: 2022-01-04 23:06:44-0500

=== Xamarin.iOS ===

Version: 15.5.0.5 (Visual Studio Enterprise)
Hash: e49c11f99
Branch: main
Build date: 2022-01-04 23:06:45-0500

=== Xamarin.Android ===

Version: 12.2.0.2 (Visual Studio Enterprise)
Commit: xamarin-android/d17-1/e9c7503
Android SDK: /Users/fak/Library/Developer/Xamarin/android-sdk-macosx
	Supported Android versions:
		4.4 (API level 19)
		7.0 (API level 24)
		7.1 (API level 25)
		8.0 (API level 26)
		8.1 (API level 27)

SDK Tools Version: 26.1.1
SDK Platform Tools Version: 31.0.3
SDK Build Tools Version: 30.0.3

Build Information: 
Mono: a5d1934
Java.Interop: xamarin/java.interop/d17-1@7ac33610
ProGuard: Guardsquare/proguard/v7.0.1@912d149
SQLite: xamarin/sqlite/3.37.1@0893b3b
Xamarin.Android Tools: xamarin/xamarin-android-tools/main@db125a7

=== Eclipse Temurin JDK ===

Java SDK: Not Found

=== Android SDK Manager ===

Version: 16.10.0.13
Hash: 1b81df5
Branch: remotes/origin/d16-10
Build date: 2021-11-12 01:17:32 UTC

=== Android Device Manager ===

Version: 16.10.0.15
Hash: 89dcc0b
Branch: remotes/origin/d16-10
Build date: 2021-11-12 01:17:52 UTC

=== Build Information ===

Release ID: 810140017
Git revision: 6f93cf55df3b7747288286e2006057c7f088b838
Build date: 2021-11-12 09:50:18-05
Build branch: release-8.10

=== Operating System ===

Mac OS X 11.6.2
Darwin 20.6.0 Darwin Kernel Version 20.6.0
    Wed Nov 10 22:23:07 PST 2021
    root:xnu-7195.141.14~1/RELEASE_X86_64 x86_64

=== Enabled user installed extensions ===

AddinMaker 1.6.0
Build Light 0.5
MSBuild Editor 2.4.0
Meadow 0.9.0.0
@praeclarum
Copy link
Contributor Author

@rolfbjarne
Copy link
Member

If you've already built xamarin-macios locally, you can do:

$ cd tests/xtro-sharpie
$ make gen-ios

and then open the ios-15.2.g.cs file, where Objective-Sharpie will have generated most (all?) our bindings, and you can use this as a starting point. It would be something like this: https://gist.github.com/rolfbjarne/92df757fee7025bf112ff10e15b9f64c (this is just a tiny part of the generated file).

@praeclarum
Copy link
Contributor Author

Great. That will save a lot of time!

@praeclarum
Copy link
Contributor Author

@rolfbjarne I have a question about how to bind their MPSShape. It is defined as:

typedef NSArray<NSNumber *> MPSShape;

Sharpie projects them as NSNumber[] which is OK, but not terribly convenient from a dev perspective. int[] would be the most convenient type. Int32 is OK because apple has a limit of ~1,000,000 elements per dimension and the shape needs to handle negative sizes as well (for unknowns). In practice, dimensions rarely exceed a couple 1,000. You would never use a float for these values.

The functions that take these arguments are usually involved in graph construction so I'm not concerned about the overhead of converting from int[] to NSArray<NSNumber*>.

Would it be OK if I use int[] instead of NSNumber[]?

@dalexsoto
Copy link
Member

dalexsoto commented Mar 2, 2022

Hello @praeclarum! Thank you for taking a stab at this!

You can use BindAs here

Some examples:

[Export ("makeShape:")]
void MakeShape ([BindAs (typeof (int []))] NSNumber [] numbers);

[return: BindAs (typeof (int []))]
[Export ("getShape:")]
NSNumber [] GetShape ();

[BindAs (typeof (int []))]
[Export ("shape:")]
NSNumber [] SomeShape { get; set; }

Hope this helps!

@praeclarum
Copy link
Contributor Author

@dalexsoto Great! That will really cleanup the API.

@chamons chamons added the feature A feature to be implemented label Mar 29, 2022
@chamons chamons added this to the Future milestone Mar 29, 2022
rolfbjarne added a commit that referenced this issue May 10, 2022
I'm very pleased to present full bindings to the MetalPerformanceShadersGraph framework!

I'm happy with how everything turned out with the exception of a few notes and questions below.

I re-implemented Apple's MNIST sample (from https://developer.apple.com/documentation/metalperformanceshadersgraph/training_a_neural_network_using_mps_graph) here:

https://gist.github.com/praeclarum/b8077771fb341a1f9c28240113e00425

It's also added as a unit test.

Fixes #14286

### Notes

* Although the API says it works on macOS 11, it has bugs and crashes with errors even with Apple’s Swift examples. It’s better on macOS 12. iOS 14 and on is fine.

* `MPSGraphSparseStorageType` has terrible names. They match Apple's but I wish they were better.

* I added convenience methods to `MPSNDArray` and `MPSGrapTensorData` and the `Variable` and `Constant` operations to decrease the amount of unsafe code users have to write. I currently do this for 32-bit floats, the most common data type.

Co-authored-by: Alex Soto <[email protected]>
Co-authored-by: Rolf Bjarne Kvinge <[email protected]>
Co-authored-by: Manuel de la Pena <[email protected]>
@ghost ghost locked as resolved and limited conversation to collaborators Jun 9, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature A feature to be implemented
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants