From a9376db37a2200b76a943d87fa21f3f2a27fc29c Mon Sep 17 00:00:00 2001 From: FoodChain <78428519+FoodChain1028@users.noreply.github.com> Date: Thu, 22 Feb 2024 10:22:23 +0000 Subject: [PATCH] feat(ios): added basic UI in MSM Benchmark (#71) * feat(ios): added basic UI in MSM Benchmark # Conflicts: # mopro-ios/MoproKit/Example/MoproKit/ViewController.swift * feat: remove redundant part and update function mapping * feat(msm benchmark): finalize display content in iOS * feat(msm benchmark): add percentage difference comparison logic of baseline * update(gpu-benchmark): document added * docs: added todo for future work --------- Co-authored-by: moven0831 --- .../src/middleware/gpu_explorations/mod.rs | 2 + mopro-ios/MoproKit/Bindings/mopro.swift | 12 +- .../MoproKit.xcodeproj/project.pbxproj | 4 + .../MoproKit/MSMBenchmarkViewController.swift | 335 ++++++++++++++++++ .../Example/MoproKit/ViewController.swift | 12 +- mopro-ios/README.md | 10 + 6 files changed, 364 insertions(+), 11 deletions(-) create mode 100644 mopro-ios/MoproKit/Example/MoproKit/MSMBenchmarkViewController.swift diff --git a/mopro-core/src/middleware/gpu_explorations/mod.rs b/mopro-core/src/middleware/gpu_explorations/mod.rs index c39759ff..a48e0c32 100644 --- a/mopro-core/src/middleware/gpu_explorations/mod.rs +++ b/mopro-core/src/middleware/gpu_explorations/mod.rs @@ -12,6 +12,7 @@ pub struct BenchmarkResult { pub total_processing_time: f64, } +// TODO: refactor fn name and add more benchmarks in the future fn single_msm() -> Result<(), Box> { let mut rng = ark_std::test_rng(); @@ -27,6 +28,7 @@ fn single_msm() -> Result<(), Box> { Ok(()) } +// TODO: figure out a way to configure the algorithm fn used // Run the msm benchmark with timing pub fn run_msm_benchmark(num_msm: Option) -> Result> { let num_msm = num_msm.unwrap_or(1000); // default to 1000 msm operations diff --git a/mopro-ios/MoproKit/Bindings/mopro.swift b/mopro-ios/MoproKit/Bindings/mopro.swift index 0ba45ffa..e2292109 100644 --- a/mopro-ios/MoproKit/Bindings/mopro.swift +++ b/mopro-ios/MoproKit/Bindings/mopro.swift @@ -509,15 +509,13 @@ public struct BenchmarkResult { public var numMsm: UInt32 public var avgProcessingTime: Double public var totalProcessingTime: Double - public var allocatedMemory: UInt32 // Default memberwise initializers are never public by default, so we // declare one manually. - public init(numMsm: UInt32, avgProcessingTime: Double, totalProcessingTime: Double, allocatedMemory: UInt32) { + public init(numMsm: UInt32, avgProcessingTime: Double, totalProcessingTime: Double) { self.numMsm = numMsm self.avgProcessingTime = avgProcessingTime self.totalProcessingTime = totalProcessingTime - self.allocatedMemory = allocatedMemory } } @@ -533,9 +531,6 @@ extension BenchmarkResult: Equatable, Hashable { if lhs.totalProcessingTime != rhs.totalProcessingTime { return false } - if lhs.allocatedMemory != rhs.allocatedMemory { - return false - } return true } @@ -543,7 +538,6 @@ extension BenchmarkResult: Equatable, Hashable { hasher.combine(numMsm) hasher.combine(avgProcessingTime) hasher.combine(totalProcessingTime) - hasher.combine(allocatedMemory) } } @@ -553,8 +547,7 @@ public struct FfiConverterTypeBenchmarkResult: FfiConverterRustBuffer { return try BenchmarkResult( numMsm: FfiConverterUInt32.read(from: &buf), avgProcessingTime: FfiConverterDouble.read(from: &buf), - totalProcessingTime: FfiConverterDouble.read(from: &buf), - allocatedMemory: FfiConverterUInt32.read(from: &buf) + totalProcessingTime: FfiConverterDouble.read(from: &buf) ) } @@ -562,7 +555,6 @@ public struct FfiConverterTypeBenchmarkResult: FfiConverterRustBuffer { FfiConverterUInt32.write(value.numMsm, into: &buf) FfiConverterDouble.write(value.avgProcessingTime, into: &buf) FfiConverterDouble.write(value.totalProcessingTime, into: &buf) - FfiConverterUInt32.write(value.allocatedMemory, into: &buf) } } diff --git a/mopro-ios/MoproKit/Example/MoproKit.xcodeproj/project.pbxproj b/mopro-ios/MoproKit/Example/MoproKit.xcodeproj/project.pbxproj index 404faedc..66d844a6 100644 --- a/mopro-ios/MoproKit/Example/MoproKit.xcodeproj/project.pbxproj +++ b/mopro-ios/MoproKit/Example/MoproKit.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 1ECF32642B728A6F00482C55 /* MSMBenchmarkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ECF32632B728A6F00482C55 /* MSMBenchmarkViewController.swift */; }; 2A418AB02AF4B1200004B747 /* CircomUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A418AAF2AF4B1200004B747 /* CircomUITests.swift */; }; 2A6E5BAF2AF499460052A601 /* CircomTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A6E5BAE2AF499460052A601 /* CircomTests.swift */; }; 4384FD09A96F702A375841EE /* Pods_MoproKit_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 78B0F9CBE5DD22576996A993 /* Pods_MoproKit_Tests.framework */; }; @@ -46,6 +47,7 @@ /* Begin PBXFileReference section */ 1E5E014D70B48C9A59F14658 /* Pods-MoproKit_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MoproKit_Example.release.xcconfig"; path = "Target Support Files/Pods-MoproKit_Example/Pods-MoproKit_Example.release.xcconfig"; sourceTree = ""; }; + 1ECF32632B728A6F00482C55 /* MSMBenchmarkViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSMBenchmarkViewController.swift; sourceTree = ""; }; 2A418AAF2AF4B1200004B747 /* CircomUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircomUITests.swift; sourceTree = ""; }; 2A6E5BAE2AF499460052A601 /* CircomTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircomTests.swift; sourceTree = ""; }; 47F8ADB0AC4168C6E874818D /* MoproKit.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = MoproKit.podspec; path = ../MoproKit.podspec; sourceTree = ""; }; @@ -131,6 +133,7 @@ 607FACD21AFB9204008FA782 /* Example for MoproKit */ = { isa = PBXGroup; children = ( + 1ECF32632B728A6F00482C55 /* MSMBenchmarkViewController.swift */, CEB804572AFF81BF0063F091 /* RSAViewController.swift */, E6E6F42D2B5860F7002F5F18 /* AnonAadhaarViewControllerNew.swift */, E69338632AFFDB1A00B80312 /* AnonAadhaarViewController.swift */, @@ -416,6 +419,7 @@ CEB804582AFF81BF0063F091 /* RSAViewController.swift in Sources */, CEB804562AFF81AF0063F091 /* KeccakZkeyViewController.swift in Sources */, 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, + 1ECF32642B728A6F00482C55 /* MSMBenchmarkViewController.swift in Sources */, CEB804502AFF81960063F091 /* KeccakSetupViewController.swift in Sources */, E6D848592B766C8C00DBAF30 /* ComplexZkeyViewController.swift in Sources */, E6E6F42E2B5860F7002F5F18 /* AnonAadhaarViewControllerNew.swift in Sources */, diff --git a/mopro-ios/MoproKit/Example/MoproKit/MSMBenchmarkViewController.swift b/mopro-ios/MoproKit/Example/MoproKit/MSMBenchmarkViewController.swift new file mode 100644 index 00000000..54ecc85a --- /dev/null +++ b/mopro-ios/MoproKit/Example/MoproKit/MSMBenchmarkViewController.swift @@ -0,0 +1,335 @@ +// +// MSMBenchmarkViewController.swift +// MoproKit_Example +// +// Created by Fuchuan Chung on 2024/2/6. +// Copyright © 2024 CocoaPods. All rights reserved. +// + +import UIKit +import MoproKit + +class MSMBenchmarkViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { + + struct AlgorithmBenchmark { + var algorithm: String + var avgMsmTime: Double + var diffWithBaseline: Double // Baseline is Arkwork Vanilla MSM + } + + var tableView: UITableView! + var resultsTableView: UITableView! + var submitButton: UIButton! + + let algorithms = ["Arkwork (Baseline)", "Example Algo 1", "Example Algo 2"] + var selectedAlgorithms: Set = [0] // Default to select the baseline MSM algorithm + + var benchmarkResults: [AlgorithmBenchmark] = [] + + typealias BenchmarkClosure = () throws -> BenchmarkResult + + // update the mapping with function in the future + let msmBenchmarkMapping: [String: (UInt32?) throws -> BenchmarkResult] = [ + "Arkwork (Baseline)": runMsmBenchmark, + // "Example Algo 1": , + // "Example Algo 2": , + ] + + override func viewDidLoad() { + super.viewDidLoad() + + // Set title + let title = UILabel() + title.text = "MSM Benchmark" + title.textColor = .white + title.textAlignment = .center + navigationItem.titleView = title + navigationController?.navigationBar.isHidden = false + navigationController?.navigationBar.prefersLargeTitles = true + + setupTableView() + setupBenchmarkButton() + setupResultsTableView() + } + + func setupTableView() { + tableView = UITableView() + tableView.delegate = self + tableView.dataSource = self + tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") + tableView.allowsMultipleSelection = true + tableView.backgroundColor = .black + tableView.translatesAutoresizingMaskIntoConstraints = false // Disable autoresizing mask to enable auto layout + view.addSubview(tableView) + + // Set Auto Layout constraints + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor) // Adjusts to half the view's height + ]) + } + + func setupResultsTableView() { + resultsTableView = UITableView() + resultsTableView.delegate = self + resultsTableView.dataSource = self + resultsTableView.register(BenchmarkResultCell.self, forCellReuseIdentifier: "BenchmarkResultCell") + resultsTableView.allowsSelection = false + resultsTableView.backgroundColor = .black + resultsTableView.translatesAutoresizingMaskIntoConstraints = false // Disable autoresizing mask to enable auto layout + view.addSubview(resultsTableView) + + // Set Auto Layout constraints + NSLayoutConstraint.activate([ + resultsTableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor), + resultsTableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + resultsTableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + resultsTableView.bottomAnchor.constraint(equalTo: submitButton.topAnchor, constant: -20) + ]) + } + + func setupBenchmarkButton() { + submitButton = UIButton(type: .system) + submitButton.frame = CGRect(x: 20, y: view.bounds.height - 80, width: view.bounds.width - 60, height: 50) + submitButton.setTitle("Generating Benchmarks", for: .normal) + submitButton.addTarget(self, action: #selector(submitAction), for: .touchUpInside) + submitButton.backgroundColor = .systemBlue + submitButton.setTitleColor(.white, for: .normal) + submitButton.layer.cornerRadius = 10 + submitButton.translatesAutoresizingMaskIntoConstraints = false // Disable autoresizing mask to enable auto layout + view.addSubview(submitButton) + + // Set Auto Layout constraints + NSLayoutConstraint.activate([ + submitButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20), + submitButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20), + submitButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20), + submitButton.heightAnchor.constraint(equalToConstant: 50) + ]) + } + + // UITableViewDataSource methods + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if tableView == self.tableView { + return algorithms.count + } else { // Results table + return benchmarkResults.count + } + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if tableView == self.tableView { + let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) + cell.textLabel?.text = "\(indexPath.row + 1). \(algorithms[indexPath.row])" + cell.backgroundColor = .black + cell.textLabel?.textColor = .white + + if selectedAlgorithms.contains(indexPath.row) { + tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none) + cell.accessoryType = .checkmark + } else { + cell.accessoryType = .none + } + return cell + } else { // Results table + guard let cell = tableView.dequeueReusableCell(withIdentifier: "BenchmarkResultCell", for: indexPath) as? BenchmarkResultCell else { + return UITableViewCell() + } + + let result = benchmarkResults[indexPath.row] + cell.nameLabel.text = result.algorithm + cell.avgTimeLabel.text = String(format: "%.2f ms", result.avgMsmTime) + cell.diffLabel.text = String(format: "%.2f %%", result.diffWithBaseline) + + // Adjust the font size or other properties as needed + cell.nameLabel.font = UIFont.systemFont(ofSize: 14) + cell.avgTimeLabel.font = UIFont.systemFont(ofSize: 14) + cell.diffLabel.font = UIFont.systemFont(ofSize: 14) + + return cell + } + } + + // UITableViewDelegate methods for algorithm selection + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + selectedAlgorithms.insert(indexPath.row) + if let cell = tableView.cellForRow(at: indexPath) { + cell.accessoryType = .checkmark + } + print("Selected: \(algorithms[indexPath.row])") + } + + func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { + selectedAlgorithms.remove(indexPath.row) + if let cell = tableView.cellForRow(at: indexPath) { + cell.accessoryType = .none + } + print("Deselected: \(algorithms[indexPath.row])") + } + + // UITableViewDelegate methods for header view + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + let headerView = UIView() + headerView.backgroundColor = UIColor.black + + // Create the header label + let headerLabel = UILabel() + headerLabel.textColor = .white + headerLabel.font = UIFont.systemFont(ofSize: 16, weight: .bold) + + // Create the horizontal white line view + let lineView = UIView() + lineView.backgroundColor = .white // Set the line color + headerView.addSubview(lineView) // Add the line view to the header view + lineView.translatesAutoresizingMaskIntoConstraints = false + + if tableView == self.tableView { + headerLabel.text = "Select MSM Algorithms" + } else { // Results table + // Define additional labels for each column if it's the results table + let nameLabel = UILabel() + configureHeaderLabel(label: nameLabel, text: "Algo Name") + + let avgTimingLabel = UILabel() + configureHeaderLabel(label: avgTimingLabel, text: "Avg Timing") + + let diffLabel = UILabel() + configureHeaderLabel(label: diffLabel, text: "Diff with Baseline") + + // Add additional labels to the header view + headerView.addSubview(nameLabel) + headerView.addSubview(avgTimingLabel) + headerView.addSubview(diffLabel) + + // Disable autoresizing mask to enable auto layout + nameLabel.translatesAutoresizingMaskIntoConstraints = false + avgTimingLabel.translatesAutoresizingMaskIntoConstraints = false + diffLabel.translatesAutoresizingMaskIntoConstraints = false + + // Set Auto Layout constraints + NSLayoutConstraint.activate([ + nameLabel.leadingAnchor.constraint(equalTo: headerView.leadingAnchor, constant: 8), + nameLabel.topAnchor.constraint(equalTo: headerView.topAnchor), + nameLabel.bottomAnchor.constraint(equalTo: lineView.topAnchor, constant: -8), + + avgTimingLabel.centerXAnchor.constraint(equalTo: headerView.centerXAnchor), + avgTimingLabel.topAnchor.constraint(equalTo: headerView.topAnchor), + avgTimingLabel.bottomAnchor.constraint(equalTo: lineView.topAnchor, constant: -8), + + diffLabel.trailingAnchor.constraint(equalTo: headerView.trailingAnchor, constant: -8), + diffLabel.topAnchor.constraint(equalTo: headerView.topAnchor), + diffLabel.bottomAnchor.constraint(equalTo: lineView.topAnchor, constant: -8), + ]) + } + + headerView.addSubview(headerLabel) + headerLabel.translatesAutoresizingMaskIntoConstraints = false + + // Set Auto Layout constraints + NSLayoutConstraint.activate([ + headerLabel.leadingAnchor.constraint(equalTo: headerView.leadingAnchor, constant: 16), + headerLabel.topAnchor.constraint(equalTo: headerView.topAnchor, constant: 8), + headerLabel.trailingAnchor.constraint(equalTo: headerView.trailingAnchor, constant: -16), + lineView.heightAnchor.constraint(equalToConstant: 1), // Line thickness + lineView.leadingAnchor.constraint(equalTo: headerView.leadingAnchor), + lineView.trailingAnchor.constraint(equalTo: headerView.trailingAnchor), + lineView.bottomAnchor.constraint(equalTo: headerView.bottomAnchor), // Position at the bottom + lineView.topAnchor.constraint(equalTo: headerLabel.bottomAnchor, constant: 8) // Space between label and line + ]) + + return headerView + } + + func configureHeaderLabel(label: UILabel, text: String) { + label.text = text + label.textColor = .white + label.font = UIFont.systemFont(ofSize: 14, weight: .bold) + } + + @objc func submitAction() { + print("Selected algorithms: \(selectedAlgorithms.map { algorithms[$0] })") + + // offload heavy computation of benchmarking in background + DispatchQueue.global(qos: .userInitiated).async { [weak self] in + guard let self = self else { return } + + var tempResults: [AlgorithmBenchmark] = [] + var baselineTiming: Double = 0.0 + + for index in self.selectedAlgorithms.sorted() { + let algorithm = self.algorithms[index] + + if let benchmarkFunction = self.msmBenchmarkMapping[algorithm] { + do { + print("Running MSM in algorithm: \(algorithm)...") + let benchData: BenchmarkResult = try benchmarkFunction(10000) + if algorithm == "Arkwork (Baseline)" { + baselineTiming = benchData.avgProcessingTime + } + + let algorithmBenchmark = AlgorithmBenchmark( + algorithm: algorithm, + avgMsmTime: benchData.avgProcessingTime, + // Calculate the percentage difference with baseline + diffWithBaseline: (benchData.avgProcessingTime - baselineTiming) / baselineTiming * 100 + ) + tempResults.append(algorithmBenchmark) + print("Result of \(algorithmBenchmark.algorithm): \(algorithmBenchmark.avgMsmTime) ms (diff: \(algorithmBenchmark.diffWithBaseline) %)") + + } catch { + print("Error running benchmark: \(error)") + } + } else { + print("No benchmark function found for \(algorithm)") + tempResults.append(AlgorithmBenchmark(algorithm: algorithm, avgMsmTime: Double.nan, diffWithBaseline: Double.nan)) + } + } + + DispatchQueue.main.async { + self.benchmarkResults = tempResults + self.resultsTableView.reloadData() + } + } + } + +} + +class BenchmarkResultCell: UITableViewCell { + let nameLabel = UILabel() + let avgTimeLabel = UILabel() + let diffLabel = UILabel() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupViews() + self.backgroundColor = .black + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupViews() { + // Add labels to the cell's contentView + [nameLabel, avgTimeLabel, diffLabel].forEach { + $0.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview($0) + $0.textColor = .white + } + + // Set Auto Layout constraints + NSLayoutConstraint.activate([ + nameLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8), + nameLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8), // Add top constraint + nameLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8), // Add bottom constraint to ensure vertical spacing is defined + + avgTimeLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), + avgTimeLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + + diffLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8), + diffLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } +} diff --git a/mopro-ios/MoproKit/Example/MoproKit/ViewController.swift b/mopro-ios/MoproKit/Example/MoproKit/ViewController.swift index 39402355..535442b5 100644 --- a/mopro-ios/MoproKit/Example/MoproKit/ViewController.swift +++ b/mopro-ios/MoproKit/Example/MoproKit/ViewController.swift @@ -19,6 +19,7 @@ class ViewController: UIViewController { let aadhaarButton = UIButton(type: .system) let aadhaarNewButton = UIButton(type: .system) let complexNewButton = UIButton(type: .system) + let msmbenchmarkButton = UIButton(type: .system) override func viewDidLoad() { super.viewDidLoad() @@ -55,6 +56,8 @@ class ViewController: UIViewController { complexNewButton.setTitle("Complex Test", for: .normal) complexNewButton.addTarget(self, action: #selector(openComplex), for: .touchUpInside) + msmbenchmarkButton.setTitle("MSM Benchmark", for: .normal) + msmbenchmarkButton.addTarget(self, action: #selector(openMSMBenchmark), for: .touchUpInside) keccakSetupButton.contentEdgeInsets = UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16) keccakZkeyButton.contentEdgeInsets = UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16) @@ -64,7 +67,7 @@ class ViewController: UIViewController { // navigationController?.navigationBar.prefersLargeTitles = true - let stackView = UIStackView(arrangedSubviews: [keccakSetupButton, keccakZkeyButton, rsaButton, aadhaarButton, aadhaarNewButton, complexNewButton]) + let stackView = UIStackView(arrangedSubviews: [keccakSetupButton, keccakZkeyButton, rsaButton, aadhaarButton, aadhaarNewButton, complexNewButton, msmbenchmarkButton]) stackView.axis = .vertical stackView.spacing = 20 stackView.translatesAutoresizingMaskIntoConstraints = false @@ -105,6 +108,11 @@ class ViewController: UIViewController { let complexVCNew = ComplexZkeyViewController() navigationController?.pushViewController(complexVCNew, animated: true) } + + @objc func openMSMBenchmark() { + let msmbenchmarkVC = MSMBenchmarkViewController() + navigationController?.pushViewController(msmbenchmarkVC, animated: true) + } } // // Make buttons bigger @@ -116,3 +124,5 @@ class ViewController: UIViewController { // stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20), // stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20) // ]) + + diff --git a/mopro-ios/README.md b/mopro-ios/README.md index 6c53f57e..e897f484 100644 --- a/mopro-ios/README.md +++ b/mopro-ios/README.md @@ -49,3 +49,13 @@ There are two ways to run tests for the example app: ```sh xcodebuild -showdestinations -workspace MoproKit.xcworkspace -scheme MoproKit-Example ``` + +## Run MSM Benchmark + +1. `cd mopro-ffi/` and convert `default=[]` into `default=["gpu-benchmarks"]` to enable `gpu-benchmarks` feature flag +2. run `make` to build the mopro-ffi library +3. `cd mopro/` and run `./scripts/build_ios.sh config-example.toml` to build IOS app and link + * remember to alter the `device_type` in `config-example.toml` + * `simulator`: running on the simulator (default) + * `device`: running on a real IOS device +4. Open `MoproKit/Example/MoproKit.xcworkspace` in Xcode and `cmd + R` for building