很久不见了各位!html
前一阵子忍不住剁手买了M1芯片的mac mini,为了弥补本身的内疚感就卖了本身的旧的mbp2017款。数据也彻底迁移到了新机器上,以前的工做也就由mbp2017完全换成mac mini了,要换就换完全点,不要给本身了留后路,哼。python
为何买mini而不是macbook系列,固然是为了减小一下尝鲜的成本,mini对于有显示器有键盘的童鞋来讲,应该是尝鲜m1芯片最有性价比的一款了(某宝只需4700)。git
另外须要说明一点,M1这个Apple Silicon虽然是arm构架,和以前使用的ipad相似,可是性能相比ipad的A12Z提高是很是大的。具体的跑分这里不展现了,全网随便搜搜就有,也就图个乐,仍是须要看看日常使用的一些状况。程序员
简单的看一下包装盒子。其实这个mini没见到实物前看起来不大,但实际拿在手中仍是感受挺大的,起码装到书包里也是不能忽视的一大个。github
拆开看看后面的接口数量,对我来讲接口多少其实不是很重要,知足基本要求就好,实在不行就拓展坞。接显示器的话,HDMI连接4K屏就很完美。macos
展现一下略显凌乱的桌面,键盘是IKBC的静音红轴,显示器是LG的27UL550,27寸4k,虽然不是4k的最佳尺寸,显示程度也比较细腻了,算是入门级4k屏幕。vim
显示分辨率设置为2304 x 1296 60HZ刚恰好,毕竟原生4k看的眼睛会瞎😓,须要注意30HZ和60HZ对鼠标流畅度影响很大,以前mbp2017在连接4k屏的时候30hz的刷新率用起来太不舒服了。ruby
使用了一个多月,大部分状况和日常使用几乎没有区别,对于我来讲就是VSCODE
+Pycharm
+一些其余的工具(paste
、esayconnect
、iterm2
等),使用起来和日常区别不是很大,前提是须要稍微花一点心思去折腾下。甚至若是不须要ide的话,直接iterm+vim插件就能解决绝大部分编译代码和使用场景。bash
还有一些经常使用软件,迅雷、QQ、微信、钉钉、爱奇艺啥的都没问题,其中有的是转译有的是原生支持,目前用起来没有明显区别。放心大胆地用吧!查看各种软件对M1芯片的支持程度:https://doesitarm.com/ 目前是1月10号,绝大部分的软件都已经支持的差很少了。微信
M1芯片的使用报告网上不少,我这里就不赘述啦,只挑我比较感兴趣的方面来讲说吧。
Pycharm和Clion在1月2号的最新更新已经原生支持了Apple Silicon(他们公司全家的产品应该都支持M1了),简单尝试了下,ZNM丝滑。
简单测试一下M1芯片8核CPU的性能,如下代码使用的库为Pytorch,作矩阵加法运算(代码借鉴于 https://github.com/pytorch/pytorch/issues/48145):
from tqdm import tqdm import torch @torch.jit.script def foo(): x = torch.ones((1024 * 12, 1024 * 12), dtype=torch.float32).cuda() y = torch.ones((1024 * 12, 1024 * 12), dtype=torch.float32).cuda() z = x + y return z if __name__ == '__main__': z0 = None for _ in tqdm(range(10000000000)): zz = foo() if z0 is None: z0 = zz else: z0 += zz
上面这段代码在1080ti上运行这段代码的速度为325,经过nvidia-smi命令能够看到GPU已经被打满了。
0%| | 11936/10000000000 [00:44<8543:10:59, 325.15it/s]
一样,使用M1芯片的CPU跑这段代码(去掉上述的cuda()
),结果为45,一样CPU已经被打满了。
二者的差距差很少为7倍,不过其实这段代码是有问题的,没有考虑在1080TI上数据从CPU到GPU传输问题(而M1不计传输耗时),所以不是客观对CPU的性能比较,看个热闹就行~。PS:我真的不会拿CPU进行训练的!
期待以后Pytorch可以运行在M1芯片的GPU上(要靠pytorch官方人员推进仍是很难,毕竟官方开发者很忙须要专一其余方向,仍是须要其余开源开发者的力量)。
关于M1芯片与2080TI的速度比较,还有一篇文章比较有意思:M1 Mac Mini Scores Higher Than My RTX 2080Ti in TensorFlow Speed Test.
目前在M1上正常使用Pytorch须要使用arm版本的conda环境编译,arm版本的conda下载地址以下:https://conda-forge.org/blog/posts/2020-10-29-macos-arm64/
安装完上述miniconda后便可按照如下步骤编译安装Pytorch:
https://github.com/pytorch/pytorch/issues/48145
这里也提供直接编译好的torch-1.8.0a0-cp38-cp38-macosx_11_0_arm64.whl
:
连接: https://pan.baidu.com/s/10WSazrv3V-Nq5vCQ7Rmh9w 密码: ipp0
额外的参考连接:http://iphonesdkdev.blogspot.com/2020/11/202011.html
其实M1芯片对我吸引最大的就是其中的神经网络引擎(以后简称ANE):
神经网络引擎,也就是neural engine
,最开始出如今A11 Bionic
也就是iphoneX/8使用的芯片,不过那个时候这个引擎只用于face id
和Animoji
。后来到了A12 Bionic
才可能被开发者经过Core ML部署到手机上,再到后来的A13 Bionic
、A14 Bionic
,一代更比一代强。
到了M1芯片使用的neural enging貌似和A14 Bionic
同样是16和至多11tflops/s的计算能力,要知道当年的GTX TAITAN X
也刚刚11TFlops,不过固然这二者的计算精度是不同的。ANE只支持fp16和(u)int8类型数据的计算。
关于ANE具体的细节能够看这里.
最简单调用苹果neural engine的方式是使用coremltools来运行,第一步固然是先安装coremltools!从官方GITHUB克隆下来而后执行:
1. cd to root of coremltools 2. mkdir build && cd build 3. cmake .. 4. make install 5. python setup.py install
建议本身编译,直接使用pip应该也能够安装(安装后须要检查一下在python的site-package中是否有libcoremlpython.so
)。
import numpy as np import coremltools as ct from coremltools.models.neural_network import datatypes, NeuralNetworkBuilder input_features = [('image', datatypes.Array(3))] output_features = [('probs', datatypes.Array(3))] weights = np.zeros((3, 3)) + 3 bias = np.ones(3) builder = NeuralNetworkBuilder(input_features, output_features) builder.add_inner_product(name='ip_layer', W=weights, b=None, input_channels=3, output_channels=3, has_bias=False, input_name='image', output_name='med') builder.add_bias(name='bias', b=bias, input_name='med', output_name='probs', shape_bias=(3,)) mlmodel = ct.models.MLModel(builder.spec) # 实际执行的时候使用了ANE out = mlmodel.predict({"image": np.array([1337,0,0], dtype=np.float32)}) print(out)
运行上面这段代码就能够调用ANE引擎,呃。怎么知道调用了捏。
咱们经过dmesg
来观察ANE是否被调用。
dmesg
命令能够检测和控制内核环缓冲,咱们能够经过这个来了解系统的启动信息,也能够经过这个命令查看mac系统是否调用了neural engine
。
执行如下命令观察窗口,当系统调用neural engine的时候会打印相关信息:
watch -n 0.1 'sudo dmesg | grep H11'
而后运行上述的.py
代码。
python coreml_ane.py {'probs': array([4012., 4012., 4012.])}
能够看到输出结果,同时咱们也能够看到刚才watch dmesg
的信息:
[14453.207863]: Sandbox: ContextStoreAgen(482) deny(1) mach-lookup com.apple.ocspdvirtual IORetu rn H11ANEIn::newUserClient(task_t, void *, UInt32, IOUserClient **) : H11ANEIn::newUserClient ty pe=2 [14453.228654]: virtual IOReturn H11ANEIn::newUserClient(task_t, void *, UInt32, IOUserClient ** ) : H11ANEIn::newUserClient : Creating default full-entitlement client [14453.228663]: virtual bool H11ANEInUserClient::init(task_t, OSDictionary *) - New UserClient f or process: aned (pid 6887) [14453.228720]: IOReturn H11ANEInUserClient::ANE_PowerOn() - client aned requesting Power On [14453.228723]: IOReturn H11ANEIn::ANE_PowerOn_gated(void *, const char *, bool) : H11ANEIn::Pow ering on ANE [14453.228728]: IOReturn H11ANEIn::ANE_PowerOn_gated(void *, const char *, bool) : H11ANEIn::AN E_PowerOn_gated - Wait until ANE gets powered up for client <ptr> retries=1 [14453.228775]: IOReturn H11ANEIn::setPowerStateGated(unsigned long, IOService *) : H11ANEIn::se tPowerStateGated: 1 [14453.234362]: H11ANEIn::power_on_hardware - FW App image... [14453.252851]: IOReturn H11ANEIn::ANE_Init(): Statistics: ColdStarts: 7, JetsamTriggeredColdSta rts: 0, Resumes: 0, ResumesFailed: 0, SuspendsSuccessful: 0, SuspendsFailed: 0 FirmwareTimeouts: 0 ANEDeInits: 6 ANEInitFailures: 0 [14453.252864]: IOReturn H11ANEIn::ANE_Init(): Work Stats: WorkSubmitted: 6 WorkBegin: 6 WorkEn ded: 6 PendingRequests: 0 [14453.253097]: H11ANEIn: ANE_ProgramCreate_gated:, ZinComputeProgramMake, get Mcache size: 0x0 [14453.253100]: H11ANEIn: ANE_ProgramCreate_gated:,Program Identifier:ANEC v1 [14453.253108]: IOReturn H11ANEIn::ANE_ProgramCreate_gated(H11ANEProgramCreateArgs *, H11ANEProg ramCreateArgsOutput *, H11ANEProgramCreateArgsAdditionalParams *) : H11ANEIn::kernel is non-muta ble kernel section [14453.253162]: IOReturn H11ANEIn::ANE_ProgramCreate_gated(H11ANEProgramCreateArgs *, H11ANEProg ramCreateArgsOutput *, H11ANEProgramCreateArgsAdditionalParams *) : WARN: H11ANEIn: Intermediate buffer size is zero [14453.253342]: IOReturn H11ANEIn::ANE_ProcessCreate_gated(H11ANEProcessCreateArgs *, H11ANEProc essCreateArgsOutput *) : programBuffer programHandle = 0x50c38b4fa8 programId = 0 [14453.254432]: virtual IOReturn H11ANEIn::newUserClient(task_t, void *, UInt32, IOUserClient ** ) : H11ANEIn::newUserClient type=1 [14453.254434]: virtual IOReturn H11ANEIn::newUserClient(task_t, void *, UInt32, IOUserClient ** ) : H11ANEIn::newUserClient : Creating direct evaluate client [14453.254438]: virtual bool H11ANEInDirectPathClient::init(task_t, OSDictionary *) - New UserCl ient for process: python3.8 (pid 63314) [14453.286145]: IOReturn H11ANEIn::FreeIntermediateBuffer(H11ANEIntermediateBufferSurfaceParams *, bool): Passing NULL for intemediate buffer. Returning from here [14453.286163]: IOReturn H11ANEIn::ANE_ProcessDestroy_gated(H11ANEProcessDestroyArgs *, bool, bo
重点看上述ANE的部分,能够看到H11ANEInUserClient::ANE_PowerOn()
->H11ANEIn::ANE_Init()
->ANE_ProcessCreate_gated
->H11ANEIn::FreeIntermediateBuffer
->ANE_ProcessDestroy_gated
的过程。
若是调用失败会打印(这种状况在没有进行受权的时候执行会出现):
[14822.089254]: AMFI: Denying core dump for pid 73626 (a.out)Sandbox: 5 duplicate reports for Co ntextStoreAgen deny(1) mach-lookup com.apple.ocspdSandbox: bird(516) deny(1) file-read-data /Use rs/guoyanzongFailed to write key 1950826800 to SMC with error code 86Failed to write key 1950826 829 to SMC with error code 86Failed to write key 1950826801 to SMC with error code 86Failed to w rite key 1950829892 to SMC with error code 86virtual IOReturn H11ANEIn::newUserClient(task_t, vo id *, UInt32, IOUserClient **) : H11ANEIn::newUserClient type=2 [14822.989968]: virtual IOReturn H11ANEIn::newUserClient(task_t, void *, UInt32, IOUserClient ** ) : H11ANEIn::newUserClient : Creating default full-entitlement client [14822.989977]: virtual bool H11ANEInUserClient::init(task_t, OSDictionary *) - process a.out (p id 73673) denied access
简单提一下若是若是想要在外部使用M1的ANE(而不是经过coremltools的方式),能够参考参考tinygrad的ANE部分(不是很成熟),做者提取了MAC系统的dyld_shared_cache_arm64e
,经过反编译能够获得dyld_shared_cache_arm64e
中具体调用的ANEServices
动态连接库:
strings dyld_shared_cache_arm64e | grep ANEServices /System/Library/PrivateFrameworks/ANEServices.framework/Versions/A/ANEServices /System/Library/PrivateFrameworks/ANEServices.framework/Versions/A/ANEServices H11ANEServicesThread /System/Library/PrivateFrameworks/ANEServices.framework/Versions/A/ANEServices /System/Library/PrivateFrameworks/ANEServices.framework/ANEServices __ZN6H11ANEL25H11ANEServicesThreadStartEPNS_26H11ANEServicesThreadParamsE /System/Library/PrivateFrameworks/ANEServices.framework/Versions/A/ANEServices /System/Library/PrivateFrameworks/ANEServices.framework/ANEServices ANEServices Versions/A/ANEServices /System/iOSSupport/System/Library/PrivateFrameworks/ANEServices.framework/Versions/A/ANEServices
提取动态连接库的仓库以下:
https://github.com/madordie/dsc_extractor
按照readme中的方式按步骤进行提取便可,咱们通常须要ANECompiler, ANEServices,AppleNeuralEngine,CoreML,Espresso
这几个。
具体调用堆栈为:libcoremlpython.so
-> CoreML
-> Espresso
-> AppleNeuralEngine
-> ANEServices
。
具体在外部调用ANE的方式这里就不详细介绍了...比较复杂须要另开一篇来说。
关于ANE的一些了解也能够看看这个:
https://www.slideshare.net/kstan2/why-you-cannot-use-neural-engine-to-run-your-nn-models-on-a11-devices
homebrew能够经过转译的方式安装,直接执行,使用命令:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
能够直接安装,以后在运行brew以前加上arch -x86_64
就能够,例如:
arch -x86_64` brew install opencv
须要注意的是经过这种方式brew安装的库默认是x86架构的!若是在编译过程当中连接x86架构的库会出现库构架不匹配的问题。
原生的brew前一阵子已经可使用了,支持了大部分已经arm64编译好的库。而且能够和Intel版本的共存,具体能够看这篇:
https://noahpeeters.de/posts/apple-silicon/homebrew-setup/
VSCODE目前仍是预览版本(原生支持M1),预览版是黄色的!大部分插件能够经过转译的方式正常工做。
不过cpp-tools
这个插件目前仍是x86的,须要经过转译来跑:
Allow extension's x64 binaries to run on Apple Silicon x64 emulator
游戏方面,目前只玩了LOL云游戏版本的,使用腾讯的START客户端,有MAC版本的,目前公测免费。
意外的流畅,玩起来和本地玩几乎没有区别,多是wifi-6的缘由,我家100M的网能够派上用场,我仍是使用无线网玩的,顺便放个视频看,玩起来毫无压力。
看了一些其余人使用window虚拟机也能够玩LOL,随着这类软件的逐渐完善,在MAC上跑window过段时间就会渐渐完美了。
使用命令:
lipo -info xxx
能够查看当前使用的可执行文件或者动态连接库是否为Arm架构,确保使用正确结构的软件。举个例子,在MAC上直接编译Pytorch源码,编译后能够查看_C.cpython-38-darwin.so
是否为arm架构:
@bogon torch % lipo -info _C.cpython-38-darwin.so // x86架构 在m1上没法正常运行 Non-fat file: _C.cpython-38-darwin.so is architecture: x86_64 // arm架构 Architectures in the fat file: _C.cpython-38-darwin.so are: x86_64 arm64
因此说,M1芯片若是遇到没法正确运行的可执行文件或者动态连接库,先用这个命令看看是否为ARM架构吧!
还有一些小bug(可能以后会解决,可是目前还存在):
目前系统是Big Sur Version 11.1
。
暂时就这些,对于M1芯片的Mac-mini来讲,一切与x86芯片的mbp使用起来没有任何区别。除了在编译连接一些源码时须要注意构架问题,麻烦些折腾些,但这不也正是程序员的快乐所在吗?
若是你与我志同道合于此,老潘很愿意与你交流;若是你喜欢老潘的内容,欢迎关注和支持。博客每周更新一篇深度原创文,关注公众号「oldpan博客」不错过最新文章。老潘也会整理一些本身的私藏,但愿能帮助到你们,公众号回复"888"获取老潘学习路线资料与文章汇总,还有更多等你挖掘。若是不想错过老潘的最新推文,请点击神秘连接。