Skip to content

Commit ed15f78

Browse files
authored
Decide attention and ANE on hardware capabilities (huggingface#29)
For Macs with >= 8 performance cores, we select CPU+GPU (original attention). Otherwise we select CPU+ANE (split einsum). Some computers (M1 Pro, 16 core GPU) might yield slightly better performance using CPU+GPU+ANE with SPLIT_EINSUM.
1 parent 8796695 commit ed15f78

File tree

5 files changed

+45
-13
lines changed

5 files changed

+45
-13
lines changed

Diffusion-macOS/Capabilities.swift

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// Capabilities.swift
3+
// Diffusion-macOS
4+
//
5+
// Created by Pedro Cuenca on 20/2/23.
6+
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
7+
//
8+
9+
import Foundation
10+
11+
let runningOnMac = true
12+
13+
#if canImport(MLCompute)
14+
import MLCompute
15+
let _hasANE = MLCDevice.ane() != nil
16+
#else
17+
let _hasANE = false
18+
#endif
19+
20+
final class Capabilities {
21+
static let hasANE = _hasANE
22+
23+
// According to my tests this is a good proxy to estimate whether CPU+GPU
24+
// or CPU+NE works better. Things may become more complicated if we
25+
// choose all compute units.
26+
static var performanceCores: Int = {
27+
var ncores: Int32 = 0
28+
var bytes = MemoryLayout<Int32>.size
29+
30+
// In M1/M2 perflevel0 refers to the performance cores and perflevel1 are the efficiency cores
31+
// In Intel there's only one performance level
32+
let result = sysctlbyname("hw.perflevel0.physicalcpu", &ncores, &bytes, nil, 0)
33+
guard result == 0 else { return 0 }
34+
return Int(ncores)
35+
}()
36+
}

Diffusion-macOS/ControlsView.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ struct ControlsView: View {
284284
}.foregroundColor(.secondary)
285285
}
286286

287-
if hasANE {
287+
if Capabilities.hasANE {
288288
Divider()
289289
DisclosureGroup(isExpanded: $disclosedAdvanced) {
290290
HStack {

Diffusion-macOS/Diffusion_macOSApp.swift

-9
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,3 @@ struct Diffusion_macOSApp: App {
1616
}
1717
}
1818
}
19-
20-
let runningOnMac = true
21-
22-
#if canImport(MLCompute)
23-
import MLCompute
24-
let hasANE = MLCDevice.ane() != nil
25-
#else
26-
let hasANE = false
27-
#endif

Diffusion.xcodeproj/project.pbxproj

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/* Begin PBXBuildFile section */
1010
EB067F872992E561004D1AD9 /* HelpContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB067F862992E561004D1AD9 /* HelpContent.swift */; };
1111
EB33A51D2954D89F00B16357 /* StableDiffusion in Frameworks */ = {isa = PBXBuildFile; productRef = EB33A51C2954D89F00B16357 /* StableDiffusion */; };
12+
EB560F0429A3C20800C0F8B8 /* Capabilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB560F0329A3C20800C0F8B8 /* Capabilities.swift */; };
1213
EBB5BA5329425BEE003A2A5B /* PipelineLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBB5BA5229425BEE003A2A5B /* PipelineLoader.swift */; };
1314
EBB5BA5829425E17003A2A5B /* Path in Frameworks */ = {isa = PBXBuildFile; productRef = EBB5BA5729425E17003A2A5B /* Path */; };
1415
EBB5BA5A29426E06003A2A5B /* Downloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBB5BA5929426E06003A2A5B /* Downloader.swift */; };
@@ -64,6 +65,7 @@
6465
/* Begin PBXFileReference section */
6566
EB067F862992E561004D1AD9 /* HelpContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpContent.swift; sourceTree = "<group>"; };
6667
EB33A51E2954E1BC00B16357 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
68+
EB560F0329A3C20800C0F8B8 /* Capabilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Capabilities.swift; sourceTree = "<group>"; };
6769
EBB5BA5229425BEE003A2A5B /* PipelineLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PipelineLoader.swift; sourceTree = "<group>"; };
6870
EBB5BA5929426E06003A2A5B /* Downloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Downloader.swift; sourceTree = "<group>"; };
6971
EBDD7DB22973200200C1C4B2 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
@@ -247,6 +249,7 @@
247249
F1552030297109C300DC009B /* ControlsView.swift */,
248250
F155203329710B3600DC009B /* StatusView.swift */,
249251
EB067F862992E561004D1AD9 /* HelpContent.swift */,
252+
EB560F0329A3C20800C0F8B8 /* Capabilities.swift */,
250253
F155202C2971093400DC009B /* Diffusion_macOS.entitlements */,
251254
F15520292971093400DC009B /* Preview Content */,
252255
);
@@ -502,6 +505,7 @@
502505
F1552031297109C300DC009B /* ControlsView.swift in Sources */,
503506
EBDD7DB62973206600C1C4B2 /* Downloader.swift in Sources */,
504507
F155203429710B3600DC009B /* StatusView.swift in Sources */,
508+
EB560F0429A3C20800C0F8B8 /* Capabilities.swift in Sources */,
505509
F15520242971093300DC009B /* Diffusion_macOSApp.swift in Sources */,
506510
EBDD7DB52973201800C1C4B2 /* ModelInfo.swift in Sources */,
507511
EBDD7DBD2977FFB300C1C4B2 /* GeneratedImageView.swift in Sources */,

Diffusion/ModelInfo.swift

+4-3
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@ struct ModelInfo {
4040

4141
extension ModelInfo {
4242
static var defaultAttention: AttentionVariant {
43-
return runningOnMac ? .original : .splitEinsum
43+
guard runningOnMac else { return .splitEinsum }
44+
guard Capabilities.hasANE else { return .original }
45+
return Capabilities.performanceCores >= 8 ? .original : .splitEinsum
4446
}
4547

46-
// TODO: heuristics per {model, device}
4748
var bestAttention: AttentionVariant {
4849
return ModelInfo.defaultAttention
4950
}
@@ -60,7 +61,7 @@ extension ModelInfo {
6061
}
6162

6263
/// Best variant for the current platform.
63-
/// Currently using `split_einsum` for iOS and `original` for macOS, but could vary depending on model.
64+
/// Currently using `split_einsum` for iOS and simple performance heuristics for macOS.
6465
var bestURL: URL { modelURL(for: bestAttention) }
6566

6667
var reduceMemory: Bool {

0 commit comments

Comments
 (0)