Apple Silicon
SkillDocs & knowledgeUse when tuning or profiling native code on Apple M-series Macs: unified memory, 16 KiB pages, Accelerate and Metal for matrix work, xctrace and leaks, Rosetta 2, or sysctl hardware queries.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Apple Silicon skill
What this skill tells your AI
The instructions your AI receives, as published by outlinedriven/outline-driven-development in .devin/skills/apple-silicon/SKILL.md and read by ahel’s review.
Contract
| Field | Bound contract |
|---|---|
| Trigger | Code runs on an M-series Mac and needs to be checked for page-size assumptions, moved onto Accelerate or Metal for matrix work, profiled with Instruments or the command-line memory tools, or diagnosed for Rosetta 2 translation. |
| Authority | Read-only: reads the host through sysctl, arch, lipo, file, xctrace, vmmap, heap, leaks, and sample, and writes traces only under the output path the user names; rollback is deleting those trace files. No remote mutation. |
| Side effect | Trace and sample files in the named output directory. Profiling attaches to the target process. |
| Done | The report names the chip and its features from sysctl, states whether the binary runs native or translated, lists every page-size assumption found in the code with its fix, and points each hotspot at the Accelerate, Metal, or threading change that addresses it. |
Inputs
- The binary or source under review, and how it is launched.
- Whether the workload is matrix or convolution heavy (Accelerate and Metal candidates) or general CPU work.
- Output directory for traces.
- Xcode command-line tools installed (
xcode-select -pprints the path).
Procedure
-
Read the hardware. All CPU cores, the GPU, and the Neural Engine share one DRAM pool, so a Metal buffer in shared storage mode needs no copy to reach the GPU, and one process's memory total includes its GPU allocations. Done when: chip name, core counts, memory size, cache line, and page size are recorded.
sysctl -n machdep.cpu.brand_string sysctl hw.physicalcpu hw.logicalcpu hw.memsize sysctl hw.cachelinesize sysctl hw.pagesize # 16384 on Apple Silicon macOS sysctl hw.optional.arm # FEAT_* flags; grep for the one in questionM4 exposes
hw.optional.arm.FEAT_SME; no M-series chip through M4 exposes non-streaming SVE, so SVE intrinsics outside streaming mode raiseSIGILLthere (seearm-sve). -
Find 16 KiB page assumptions. Anything that hard-codes 4096 for
mmapoffsets, guard pages, or allocator arenas breaks or wastes memory. Done when: every page-size constant in the code readssysconf(_SC_PAGESIZE)orgetpagesize()instead.size_t page = sysconf(_SC_PAGESIZE); /* 16384 here, 4096 on x86 CI */ void *buf = aligned_alloc(page, size); mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);An
mmapoffsetthat is not a multiple of the page size fails withEINVAL; a test suite that only ran on 4 KiB Linux hosts will not have caught it. -
Route matrix work through Accelerate. The AMX coprocessor has no public instruction-level documentation; Accelerate (BLAS, LAPACK, vDSP, BNNS) is the supported way onto it. Done when: the hot GEMM calls
cblas_sgemmor the vDSP equivalent and the leading dimensions match the storage order.#include <Accelerate/Accelerate.h> void matmul(const float *A, const float *B, float *C, int M, int N, int K) { cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, M, N, K, 1.0f, A, K, B, N, 0.0f, C, N); }clang -O2 -framework Accelerate -o gemm gemm.c -
Move large GPU-friendly kernels to Metal Performance Shaders. Allocate buffers with
MTLResourceStorageModeSharedso the CPU and GPU read the same memory. Done when: the MPS kernel runs on a real device (the simulator has no Metal GPU) and its result matches the CPU reference.#import <Metal/Metal.h> #import <MetalPerformanceShaders/MetalPerformanceShaders.h> id<MTLDevice> device = MTLCreateSystemDefaultDevice(); id<MTLCommandQueue> queue = [device newCommandQueue]; MPSMatrixMultiplication *gemm = [[MPSMatrixMultiplication alloc] initWithDevice:device transposeLeft:NO transposeRight:NO resultRows:M resultColumns:N interiorColumns:K alpha:1.0 beta:0.0]; -
Profile with Instruments from the command line.
xctracerecords a template into a.tracebundle that Instruments opens;--toclists what a trace holds. Done when: a Time Profiler trace and an Allocations trace exist for the workload.xctrace record --template 'Time Profiler' --output app.trace --launch -- ./app xctrace record --template 'Allocations' --output alloc.trace --launch -- ./app xctrace record --template 'Leaks' --output leaks.trace --launch -- ./app xctrace export --input app.trace --tocTemplate Answers Time Profiler Where CPU time goes, and on which core type Allocations Heap growth and the call trees that allocate Leaks Blocks with no remaining reference System Trace Thread scheduling and system calls In Xcode the same templates are under Product, then Profile.
-
Inspect a running process without Instruments. Done when: the leak or growth is attributed to a call stack.
vmmap <pid> # regions and their sizes heap <pid> # heap objects by class and size leaks <pid> # unreferenced blocks with backtraces sample <pid> 5 -file sample.txt # 5 seconds of stack samples -
Check for Rosetta 2. A translated x86_64 process reports
sysctl.proc_translatedas 1. Done when: the binary is known to be arm64, universal, or x86_64-only, and an x86_64-only hot path has a plan to ship arm64.sysctl -n sysctl.proc_translated # 1 inside a translated process lipo -info app # architectures in the binary file app arch -arm64 ./app # force a slice of a universal binary arch -x86_64 ./app -
Build for the chip.
-mcpu=apple-m1through-mcpu=apple-m4are accepted by the installed clang; pick the oldest chip the binary must run on. Heavy threads request a performance-core class throughpthread_set_qos_class_self_np(QOS_CLASS_USER_INITIATED, 0); the scheduler, not the program, decides the core. Done when: the release build passes-arch arm64and a-mcpuno newer than the deployment floor.clang -arch arm64 -O3 -mcpu=apple-m1 -o app app.c
Failure and recovery
| Symptom | Cause | Fix |
|---|---|---|
mmap fails with EINVAL | Offset or length assumes 4 KiB pages | Round with sysconf(_SC_PAGESIZE). |
Slow binary, proc_translated is 1 | Running under Rosetta 2 | Build arm64 or universal. |
MTLCreateSystemDefaultDevice returns nil | Simulator, or no GPU access in the sandbox | Run on the device; check the entitlement. |
Wrong results from cblas_sgemm | Row or column major mismatch | Match CblasRowMajor and the leading dimensions to the storage. |
Empty xctrace recording | Target not signed for debugging, or launched outside the developer tools | Sign with get-task-allow, or record from Xcode. |
sysctl: unknown oid | Key differs by chip or macOS | List with sysctl hw.optional.arm and pick the key that exists. |
Output
A report to chat naming the chip and feature flags, the native or translated status of each binary, every page-size assumption with its fix, the profiler templates recorded and where the trace files are, and the Accelerate, Metal, or threading change proposed for each hotspot.
Signals
- GitHub stars
- 52
- Forks
- 9
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
apple-silicon- Source
- github.com/outlinedriven/outline-driven-development