diff --git a/mv3/apple/ExecuTorchDemo/ExecuTorchDemo.xcodeproj/project.pbxproj b/mv3/apple/ExecuTorchDemo/ExecuTorchDemo.xcodeproj/project.pbxproj index 324f4eb832..92405a4298 100644 --- a/mv3/apple/ExecuTorchDemo/ExecuTorchDemo.xcodeproj/project.pbxproj +++ b/mv3/apple/ExecuTorchDemo/ExecuTorchDemo.xcodeproj/project.pbxproj @@ -15,13 +15,16 @@ 032C02032AC47CFB002955E1 /* mv3_xnnpack_fp32.pte in Resources */ = {isa = PBXBuildFile; fileRef = 032C01FC2AC47CFB002955E1 /* mv3_xnnpack_fp32.pte */; }; 032C02082AC47CFB002955E1 /* imagenet_classes.txt in Resources */ = {isa = PBXBuildFile; fileRef = 032C02012AC47CFB002955E1 /* imagenet_classes.txt */; }; 03672A662DE1226100147123 /* backend_coreml in Frameworks */ = {isa = PBXBuildFile; productRef = 03672A652DE1226100147123 /* backend_coreml */; }; + CAFE00010000000000000000 /* backend_mlx in Frameworks */ = {isa = PBXBuildFile; productRef = CAFE00010000000000000002 /* backend_mlx */; }; 03672A6A2DE1226100147123 /* backend_xnnpack in Frameworks */ = {isa = PBXBuildFile; productRef = 03672A692DE1226100147123 /* backend_xnnpack */; }; 03672A752DE144CF00147123 /* executorch_debug in Frameworks */ = {isa = PBXBuildFile; productRef = 03672A742DE144CF00147123 /* executorch_debug */; }; 03672A772DE1457900147123 /* backend_coreml in Frameworks */ = {isa = PBXBuildFile; productRef = 03672A762DE1457900147123 /* backend_coreml */; }; + CAFE00010000000000000001 /* backend_mlx in Frameworks */ = {isa = PBXBuildFile; productRef = CAFE00010000000000000003 /* backend_mlx */; }; 03672A7B2DE1457900147123 /* backend_xnnpack in Frameworks */ = {isa = PBXBuildFile; productRef = 03672A7A2DE1457900147123 /* backend_xnnpack */; }; 036834D52ACB710D00BA100F /* mv3.pte in Resources */ = {isa = PBXBuildFile; fileRef = 036834D42ACB710D00BA100F /* mv3.pte */; }; 036834D62ACB710D00BA100F /* mv3.pte in Resources */ = {isa = PBXBuildFile; fileRef = 036834D42ACB710D00BA100F /* mv3.pte */; }; 036834D82ACB893700BA100F /* mv3_coreml_all.pte in Resources */ = {isa = PBXBuildFile; fileRef = 036834D72ACB893700BA100F /* mv3_coreml_all.pte */; }; + CAFE00010000000000000004 /* mv3_mlx.pte in Resources */ = {isa = PBXBuildFile; fileRef = CAFE00010000000000000006 /* mv3_mlx.pte */; }; 03B184962E1FA1E400246294 /* kernels_optimized in Frameworks */ = {isa = PBXBuildFile; productRef = 03B184952E1FA1E400246294 /* kernels_optimized */; }; 03B184982E1FA1F400246294 /* kernels_optimized in Frameworks */ = {isa = PBXBuildFile; productRef = 03B184972E1FA1F400246294 /* kernels_optimized */; }; 03C818192AC671980084CC29 /* Samoyed.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03C818182AC671980084CC29 /* Samoyed.jpg */; }; @@ -37,6 +40,7 @@ 03C818482AC7BF470084CC29 /* imagenet_classes.txt in Resources */ = {isa = PBXBuildFile; fileRef = 032C02012AC47CFB002955E1 /* imagenet_classes.txt */; }; 03C8184A2AC7BF470084CC29 /* mv3_xnnpack_fp32.pte in Resources */ = {isa = PBXBuildFile; fileRef = 032C01FC2AC47CFB002955E1 /* mv3_xnnpack_fp32.pte */; }; 03C8DC7C2AE2533C0064384A /* mv3_coreml_all.pte in Resources */ = {isa = PBXBuildFile; fileRef = 036834D72ACB893700BA100F /* mv3_coreml_all.pte */; }; + CAFE00010000000000000005 /* mv3_mlx.pte in Resources */ = {isa = PBXBuildFile; fileRef = CAFE00010000000000000006 /* mv3_mlx.pte */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -96,6 +100,7 @@ 032C02012AC47CFB002955E1 /* imagenet_classes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = imagenet_classes.txt; sourceTree = ""; }; 036834D42ACB710D00BA100F /* mv3.pte */ = {isa = PBXFileReference; lastKnownFileType = file; path = mv3.pte; sourceTree = ""; }; 036834D72ACB893700BA100F /* mv3_coreml_all.pte */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mv3_coreml_all.pte; sourceTree = ""; }; + CAFE00010000000000000006 /* mv3_mlx.pte */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mv3_mlx.pte; sourceTree = ""; }; 03C8180A2AC66FC30084CC29 /* MobileNetClassifierTest.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MobileNetClassifierTest.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 03C818182AC671980084CC29 /* Samoyed.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = Samoyed.jpg; sourceTree = ""; }; 03C8181C2AC69C280084CC29 /* Arctic fox.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "Arctic fox.jpg"; sourceTree = ""; }; @@ -116,6 +121,7 @@ 03672A6A2DE1226100147123 /* backend_xnnpack in Frameworks */, 03B184962E1FA1E400246294 /* kernels_optimized in Frameworks */, 03672A662DE1226100147123 /* backend_coreml in Frameworks */, + CAFE00010000000000000000 /* backend_mlx in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -136,6 +142,7 @@ 03672A7B2DE1457900147123 /* backend_xnnpack in Frameworks */, 03B184982E1FA1F400246294 /* kernels_optimized in Frameworks */, 03672A772DE1457900147123 /* backend_coreml in Frameworks */, + CAFE00010000000000000001 /* backend_mlx in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -232,6 +239,7 @@ children = ( 032C02012AC47CFB002955E1 /* imagenet_classes.txt */, 036834D72ACB893700BA100F /* mv3_coreml_all.pte */, + CAFE00010000000000000006 /* mv3_mlx.pte */, 032C01FC2AC47CFB002955E1 /* mv3_xnnpack_fp32.pte */, 036834D42ACB710D00BA100F /* mv3.pte */, ); @@ -290,6 +298,7 @@ name = App; packageProductDependencies = ( 03672A652DE1226100147123 /* backend_coreml */, + CAFE00010000000000000002 /* backend_mlx */, 03672A692DE1226100147123 /* backend_xnnpack */, 03B184952E1FA1E400246294 /* kernels_optimized */, ); @@ -334,6 +343,7 @@ name = MobileNetClassifierTest; packageProductDependencies = ( 03672A762DE1457900147123 /* backend_coreml */, + CAFE00010000000000000003 /* backend_mlx */, 03672A7A2DE1457900147123 /* backend_xnnpack */, 03B184972E1FA1F400246294 /* kernels_optimized */, ); @@ -411,6 +421,7 @@ buildActionMask = 2147483647; files = ( 036834D82ACB893700BA100F /* mv3_coreml_all.pte in Resources */, + CAFE00010000000000000004 /* mv3_mlx.pte in Resources */, 036834D52ACB710D00BA100F /* mv3.pte in Resources */, 032C02082AC47CFB002955E1 /* imagenet_classes.txt in Resources */, 032C02032AC47CFB002955E1 /* mv3_xnnpack_fp32.pte in Resources */, @@ -428,6 +439,7 @@ 03C818192AC671980084CC29 /* Samoyed.jpg in Resources */, 03C8181F2AC69DFF0084CC29 /* hot pot.jpg in Resources */, 03C8DC7C2AE2533C0064384A /* mv3_coreml_all.pte in Resources */, + CAFE00010000000000000005 /* mv3_mlx.pte in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -786,7 +798,7 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/pytorch/executorch"; requirement = { - branch = "swiftpm-1.1.0"; + branch = "swiftpm-1.5.0.20260902"; kind = branch; }; }; @@ -798,6 +810,11 @@ package = 03672A642DE1226100147123 /* XCRemoteSwiftPackageReference "executorch" */; productName = backend_coreml; }; + CAFE00010000000000000002 /* backend_mlx */ = { + isa = XCSwiftPackageProductDependency; + package = 03672A642DE1226100147123 /* XCRemoteSwiftPackageReference "executorch" */; + productName = backend_mlx; + }; 03672A692DE1226100147123 /* backend_xnnpack */ = { isa = XCSwiftPackageProductDependency; package = 03672A642DE1226100147123 /* XCRemoteSwiftPackageReference "executorch" */; @@ -813,6 +830,11 @@ package = 03672A642DE1226100147123 /* XCRemoteSwiftPackageReference "executorch" */; productName = backend_coreml; }; + CAFE00010000000000000003 /* backend_mlx */ = { + isa = XCSwiftPackageProductDependency; + package = 03672A642DE1226100147123 /* XCRemoteSwiftPackageReference "executorch" */; + productName = backend_mlx; + }; 03672A7A2DE1457900147123 /* backend_xnnpack */ = { isa = XCSwiftPackageProductDependency; package = 03672A642DE1226100147123 /* XCRemoteSwiftPackageReference "executorch" */; diff --git a/mv3/apple/ExecuTorchDemo/ExecuTorchDemo/Resources/Models/MobileNet/imagenet_classes.txt b/mv3/apple/ExecuTorchDemo/ExecuTorchDemo/Resources/Models/MobileNet/imagenet_classes.txt new file mode 100644 index 0000000000..888d6f51dd --- /dev/null +++ b/mv3/apple/ExecuTorchDemo/ExecuTorchDemo/Resources/Models/MobileNet/imagenet_classes.txt @@ -0,0 +1,1000 @@ +tench +goldfish +great white shark +tiger shark +hammerhead +electric ray +stingray +cock +hen +ostrich +brambling +goldfinch +house finch +junco +indigo bunting +robin +bulbul +jay +magpie +chickadee +water ouzel +kite +bald eagle +vulture +great grey owl +European fire salamander +common newt +eft +spotted salamander +axolotl +bullfrog +tree frog +tailed frog +loggerhead +leatherback turtle +mud turtle +terrapin +box turtle +banded gecko +common iguana +American chameleon +whiptail +agama +frilled lizard +alligator lizard +Gila monster +green lizard +African chameleon +Komodo dragon +African crocodile +American alligator +triceratops +thunder snake +ringneck snake +hognose snake +green snake +king snake +garter snake +water snake +vine snake +night snake +boa constrictor +rock python +Indian cobra +green mamba +sea snake +horned viper +diamondback +sidewinder +trilobite +harvestman +scorpion +black and gold garden spider +barn spider +garden spider +black widow +tarantula +wolf spider +tick +centipede +black grouse +ptarmigan +ruffed grouse +prairie chicken +peacock +quail +partridge +African grey +macaw +sulphur-crested cockatoo +lorikeet +coucal +bee eater +hornbill +hummingbird +jacamar +toucan +drake +red-breasted merganser +goose +black swan +tusker +echidna +platypus +wallaby +koala +wombat +jellyfish +sea anemone +brain coral +flatworm +nematode +conch +snail +slug +sea slug +chiton +chambered nautilus +Dungeness crab +rock crab +fiddler crab +king crab +American lobster +spiny lobster +crayfish +hermit crab +isopod +white stork +black stork +spoonbill +flamingo +little blue heron +American egret +bittern +crane +limpkin +European gallinule +American coot +bustard +ruddy turnstone +red-backed sandpiper +redshank +dowitcher +oystercatcher +pelican +king penguin +albatross +grey whale +killer whale +dugong +sea lion +Chihuahua +Japanese spaniel +Maltese dog +Pekinese +Shih-Tzu +Blenheim spaniel +papillon +toy terrier +Rhodesian ridgeback +Afghan hound +basset +beagle +bloodhound +bluetick +black-and-tan coonhound +Walker hound +English foxhound +redbone +borzoi +Irish wolfhound +Italian greyhound +whippet +Ibizan hound +Norwegian elkhound +otterhound +Saluki +Scottish deerhound +Weimaraner +Staffordshire bullterrier +American Staffordshire terrier +Bedlington terrier +Border terrier +Kerry blue terrier +Irish terrier +Norfolk terrier +Norwich terrier +Yorkshire terrier +wire-haired fox terrier +Lakeland terrier +Sealyham terrier +Airedale +cairn +Australian terrier +Dandie Dinmont +Boston bull +miniature schnauzer +giant schnauzer +standard schnauzer +Scotch terrier +Tibetan terrier +silky terrier +soft-coated wheaten terrier +West Highland white terrier +Lhasa +flat-coated retriever +curly-coated retriever +golden retriever +Labrador retriever +Chesapeake Bay retriever +German short-haired pointer +vizsla +English setter +Irish setter +Gordon setter +Brittany spaniel +clumber +English springer +Welsh springer spaniel +cocker spaniel +Sussex spaniel +Irish water spaniel +kuvasz +schipperke +groenendael +malinois +briard +kelpie +komondor +Old English sheepdog +Shetland sheepdog +collie +Border collie +Bouvier des Flandres +Rottweiler +German shepherd +Doberman +miniature pinscher +Greater Swiss Mountain dog +Bernese mountain dog +Appenzeller +EntleBucher +boxer +bull mastiff +Tibetan mastiff +French bulldog +Great Dane +Saint Bernard +Eskimo dog +malamute +Siberian husky +dalmatian +affenpinscher +basenji +pug +Leonberg +Newfoundland +Great Pyrenees +Samoyed +Pomeranian +chow +keeshond +Brabancon griffon +Pembroke +Cardigan +toy poodle +miniature poodle +standard poodle +Mexican hairless +timber wolf +white wolf +red wolf +coyote +dingo +dhole +African hunting dog +hyena +red fox +kit fox +Arctic fox +grey fox +tabby +tiger cat +Persian cat +Siamese cat +Egyptian cat +cougar +lynx +leopard +snow leopard +jaguar +lion +tiger +cheetah +brown bear +American black bear +ice bear +sloth bear +mongoose +meerkat +tiger beetle +ladybug +ground beetle +long-horned beetle +leaf beetle +dung beetle +rhinoceros beetle +weevil +fly +bee +ant +grasshopper +cricket +walking stick +cockroach +mantis +cicada +leafhopper +lacewing +dragonfly +damselfly +admiral +ringlet +monarch +cabbage butterfly +sulphur butterfly +lycaenid +starfish +sea urchin +sea cucumber +wood rabbit +hare +Angora +hamster +porcupine +fox squirrel +marmot +beaver +guinea pig +sorrel +zebra +hog +wild boar +warthog +hippopotamus +ox +water buffalo +bison +ram +bighorn +ibex +hartebeest +impala +gazelle +Arabian camel +llama +weasel +mink +polecat +black-footed ferret +otter +skunk +badger +armadillo +three-toed sloth +orangutan +gorilla +chimpanzee +gibbon +siamang +guenon +patas +baboon +macaque +langur +colobus +proboscis monkey +marmoset +capuchin +howler monkey +titi +spider monkey +squirrel monkey +Madagascar cat +indri +Indian elephant +African elephant +lesser panda +giant panda +barracouta +eel +coho +rock beauty +anemone fish +sturgeon +gar +lionfish +puffer +abacus +abaya +academic gown +accordion +acoustic guitar +aircraft carrier +airliner +airship +altar +ambulance +amphibian +analog clock +apiary +apron +ashcan +assault rifle +backpack +bakery +balance beam +balloon +ballpoint +Band Aid +banjo +bannister +barbell +barber chair +barbershop +barn +barometer +barrel +barrow +baseball +basketball +bassinet +bassoon +bathing cap +bath towel +bathtub +beach wagon +beacon +beaker +bearskin +beer bottle +beer glass +bell cote +bib +bicycle-built-for-two +bikini +binder +binoculars +birdhouse +boathouse +bobsled +bolo tie +bonnet +bookcase +bookshop +bottlecap +bow +bow tie +brass +brassiere +breakwater +breastplate +broom +bucket +buckle +bulletproof vest +bullet train +butcher shop +cab +caldron +candle +cannon +canoe +can opener +cardigan +car mirror +carousel +carpenter's kit +carton +car wheel +cash machine +cassette +cassette player +castle +catamaran +CD player +cello +cellular telephone +chain +chainlink fence +chain mail +chain saw +chest +chiffonier +chime +china cabinet +Christmas stocking +church +cinema +cleaver +cliff dwelling +cloak +clog +cocktail shaker +coffee mug +coffeepot +coil +combination lock +computer keyboard +confectionery +container ship +convertible +corkscrew +cornet +cowboy boot +cowboy hat +cradle +crane +crash helmet +crate +crib +Crock Pot +croquet ball +crutch +cuirass +dam +desk +desktop computer +dial telephone +diaper +digital clock +digital watch +dining table +dishrag +dishwasher +disk brake +dock +dogsled +dome +doormat +drilling platform +drum +drumstick +dumbbell +Dutch oven +electric fan +electric guitar +electric locomotive +entertainment center +envelope +espresso maker +face powder +feather boa +file +fireboat +fire engine +fire screen +flagpole +flute +folding chair +football helmet +forklift +fountain +fountain pen +four-poster +freight car +French horn +frying pan +fur coat +garbage truck +gasmask +gas pump +goblet +go-kart +golf ball +golfcart +gondola +gong +gown +grand piano +greenhouse +grille +grocery store +guillotine +hair slide +hair spray +half track +hammer +hamper +hand blower +hand-held computer +handkerchief +hard disc +harmonica +harp +harvester +hatchet +holster +home theater +honeycomb +hook +hoopskirt +horizontal bar +horse cart +hourglass +iPod +iron +jack-o'-lantern +jean +jeep +jersey +jigsaw puzzle +jinrikisha +joystick +kimono +knee pad +knot +lab coat +ladle +lampshade +laptop +lawn mower +lens cap +letter opener +library +lifeboat +lighter +limousine +liner +lipstick +Loafer +lotion +loudspeaker +loupe +lumbermill +magnetic compass +mailbag +mailbox +maillot +maillot +manhole cover +maraca +marimba +mask +matchstick +maypole +maze +measuring cup +medicine chest +megalith +microphone +microwave +military uniform +milk can +minibus +miniskirt +minivan +missile +mitten +mixing bowl +mobile home +Model T +modem +monastery +monitor +moped +mortar +mortarboard +mosque +mosquito net +motor scooter +mountain bike +mountain tent +mouse +mousetrap +moving van +muzzle +nail +neck brace +necklace +nipple +notebook +obelisk +oboe +ocarina +odometer +oil filter +organ +oscilloscope +overskirt +oxcart +oxygen mask +packet +paddle +paddlewheel +padlock +paintbrush +pajama +palace +panpipe +paper towel +parachute +parallel bars +park bench +parking meter +passenger car +patio +pay-phone +pedestal +pencil box +pencil sharpener +perfume +Petri dish +photocopier +pick +pickelhaube +picket fence +pickup +pier +piggy bank +pill bottle +pillow +ping-pong ball +pinwheel +pirate +pitcher +plane +planetarium +plastic bag +plate rack +plow +plunger +Polaroid camera +pole +police van +poncho +pool table +pop bottle +pot +potter's wheel +power drill +prayer rug +printer +prison +projectile +projector +puck +punching bag +purse +quill +quilt +racer +racket +radiator +radio +radio telescope +rain barrel +recreational vehicle +reel +reflex camera +refrigerator +remote control +restaurant +revolver +rifle +rocking chair +rotisserie +rubber eraser +rugby ball +rule +running shoe +safe +safety pin +saltshaker +sandal +sarong +sax +scabbard +scale +school bus +schooner +scoreboard +screen +screw +screwdriver +seat belt +sewing machine +shield +shoe shop +shoji +shopping basket +shopping cart +shovel +shower cap +shower curtain +ski +ski mask +sleeping bag +slide rule +sliding door +slot +snorkel +snowmobile +snowplow +soap dispenser +soccer ball +sock +solar dish +sombrero +soup bowl +space bar +space heater +space shuttle +spatula +speedboat +spider web +spindle +sports car +spotlight +stage +steam locomotive +steel arch bridge +steel drum +stethoscope +stole +stone wall +stopwatch +stove +strainer +streetcar +stretcher +studio couch +stupa +submarine +suit +sundial +sunglass +sunglasses +sunscreen +suspension bridge +swab +sweatshirt +swimming trunks +swing +switch +syringe +table lamp +tank +tape player +teapot +teddy +television +tennis ball +thatch +theater curtain +thimble +thresher +throne +tile roof +toaster +tobacco shop +toilet seat +torch +totem pole +tow truck +toyshop +tractor +trailer truck +tray +trench coat +tricycle +trimaran +tripod +triumphal arch +trolleybus +trombone +tub +turnstile +typewriter keyboard +umbrella +unicycle +upright +vacuum +vase +vault +velvet +vending machine +vestment +viaduct +violin +volleyball +waffle iron +wall clock +wallet +wardrobe +warplane +washbasin +washer +water bottle +water jug +water tower +whiskey jug +whistle +wig +window screen +window shade +Windsor tie +wine bottle +wing +wok +wooden spoon +wool +worm fence +wreck +yawl +yurt +web site +comic book +crossword puzzle +street sign +traffic light +book jacket +menu +plate +guacamole +consomme +hot pot +trifle +ice cream +ice lolly +French loaf +bagel +pretzel +cheeseburger +hotdog +mashed potato +head cabbage +broccoli +cauliflower +zucchini +spaghetti squash +acorn squash +butternut squash +cucumber +artichoke +bell pepper +cardoon +mushroom +Granny Smith +strawberry +orange +lemon +fig +pineapple +banana +jackfruit +custard apple +pomegranate +hay +carbonara +chocolate sauce +dough +meat loaf +pizza +potpie +burrito +red wine +espresso +cup +eggnog +alp +bubble +cliff +coral reef +geyser +lakeside +promontory +sandbar +seashore +valley +volcano +ballplayer +groom +scuba diver +rapeseed +daisy +yellow lady's slipper +corn +acorn +hip +buckeye +coral fungus +agaric +gyromitra +stinkhorn +earthstar +hen-of-the-woods +bolete +ear +toilet tissue \ No newline at end of file diff --git a/mv3/apple/ExecuTorchDemo/ExecuTorchDemo/Sources/App/ClassificationController.swift b/mv3/apple/ExecuTorchDemo/ExecuTorchDemo/Sources/App/ClassificationController.swift index 5b0b7894ac..dc3594ef20 100644 --- a/mv3/apple/ExecuTorchDemo/ExecuTorchDemo/Sources/App/ClassificationController.swift +++ b/mv3/apple/ExecuTorchDemo/ExecuTorchDemo/Sources/App/ClassificationController.swift @@ -13,6 +13,17 @@ import SwiftUI enum Mode: String, CaseIterable { case xnnpack = "XNNPACK" case coreML = "Core ML" + case mlx = "MLX" + + static var allCases: [Mode] { + // The MLX delegate reports itself unavailable on the simulator, so loading a + // model there fails. Offer it only where it can run. + #if targetEnvironment(simulator) + return [.xnnpack, .coreML] + #else + return [.xnnpack, .coreML, .mlx] + #endif + } } class ClassificationController: ObservableObject { @@ -62,6 +73,8 @@ class ClassificationController: ObservableObject { switch mode { case .coreML: modelFileName = "mv3_coreml_all" + case .mlx: + modelFileName = "mv3_mlx" case .xnnpack: modelFileName = "mv3_xnnpack_fp32" } diff --git a/mv3/apple/ExecuTorchDemo/ExecuTorchDemo/Sources/MobileNet/Test/MobileNetClassifierTest.swift b/mv3/apple/ExecuTorchDemo/ExecuTorchDemo/Sources/MobileNet/Test/MobileNetClassifierTest.swift index 0738d293f1..4ee6d40c91 100644 --- a/mv3/apple/ExecuTorchDemo/ExecuTorchDemo/Sources/MobileNet/Test/MobileNetClassifierTest.swift +++ b/mv3/apple/ExecuTorchDemo/ExecuTorchDemo/Sources/MobileNet/Test/MobileNetClassifierTest.swift @@ -25,6 +25,14 @@ final class MobileNetClassifierTest: XCTestCase { try run(model: "mv3_xnnpack_fp32") } + func testV3WithMLXBackend() throws { + #if targetEnvironment(simulator) + throw XCTSkip("The MLX delegate reports itself unavailable on the simulator.") + #else + try run(model: "mv3_mlx") + #endif + } + private func run(model modelName: String) throws { guard let modelFilePath = Bundle(for: type(of: self)) diff --git a/mv3/apple/ExecuTorchDemo/README.md b/mv3/apple/ExecuTorchDemo/README.md index 9ddba7818b..6d5ba2fde8 100644 --- a/mv3/apple/ExecuTorchDemo/README.md +++ b/mv3/apple/ExecuTorchDemo/README.md @@ -4,10 +4,11 @@ Welcome to the tutorial on setting up the ExecuTorch iOS Demo App! This app uses the [MobileNet v3](https://pytorch.org/vision/main/models/mobilenetv3.html) model to -process live camera images leveraging two different backends: -[XNNPACK](https://github.com/google/XNNPACK) and +process live camera images leveraging three different backends: +[XNNPACK](https://github.com/google/XNNPACK), [Core ML](https://developer.apple.com/documentation/coreml) -(Xcode 15+ and iOS 17+ only). +(Xcode 15+ and iOS 17+ only), and +[MLX](https://github.com/ml-explore/mlx) (Apple Silicon devices only).

@@ -69,7 +70,8 @@ Now, let's move on to exporting and bundling the MobileNet v3 model. ### 1. Export Model -Export the MobileNet v3 model using the command line with Core ML and XNNPACK backends +Export the MobileNet v3 model using the command line with Core ML, XNNPACK, and MLX +backends. The MLX model is only exported on macOS, where that delegate is available. ```bash python3 mv3/python/export.py diff --git a/mv3/python/export.py b/mv3/python/export.py index a9258e9ccc..2fc330b1f4 100644 --- a/mv3/python/export.py +++ b/mv3/python/export.py @@ -12,6 +12,13 @@ from executorch.backends.xnnpack.partition.xnnpack_partitioner import XnnpackPartitioner from executorch.exir import EdgeCompileConfig, to_edge_transform_and_lower +try: + from executorch.backends.mlx import MLXPartitioner +except ImportError: + # The MLX delegate is only built into the macOS package, so a run on another + # platform exports the rest rather than nothing at all. + MLXPartitioner = None + def main() -> None: model = models.mobilenet_v3_small(weights="DEFAULT").eval() @@ -39,6 +46,14 @@ def main() -> None: with open("mv3_xnnpack_fp32.pte", "wb") as file: et_program_xnnpack.write_to_file(file) + if MLXPartitioner is not None: + et_program_mlx = to_edge_transform_and_lower( + torch.export.export(model, sample_inputs), + partitioner=[MLXPartitioner()], + ).to_executorch() + with open("mv3_mlx.pte", "wb") as file: + et_program_mlx.write_to_file(file) + if __name__ == "__main__": main()