Macbook Pro (Retina, 15-inch, Late-2013) 外置显卡经验分享

前言

笔者认为,在仅考虑一台计算机的前提下,若想同时兼顾外出便携性及与台式电脑媲美的高性能,像是模块化一般的产品是一种比较理想的选择,将外出时不需要的部分留在家中。就像许多年前,笔记本有过采用双层可拆卸设计的笔记本电脑,在那个软驱和光驱还流行的年代(印象中大概是奔腾3为主流的那个时候),下层是软驱、光驱和额外的电池,上层是笔记本电脑的主要部分。当前些年 Sony VAIO Z 系列推出包含显卡及光驱的外接模块时,其理念便是如此。

随着 Thunderbolt 3 接口的推广,现在已经可以见到许多基于 Thunderbolt 3 的外置显卡盒子及支援的笔记本电脑。然而,笔者的 Macbook Pro (Retina, 15-inch, Late-2013, with NVIDIA Geforce GT750M) (以下简称 RMBP15)仅有两个 Thunderbolt 2 接口,在 Akitio Thunder 2 盒子的支持设备列表中并不包括外置显卡,因此虽然通过 Thunderbolt 2 接口可以实现外置显卡但是会伴随着一些小问题。

 

硬件

笔者使用的设备为 RMBP15 Late-2013 with GT750M,Akitio Thunder 2 及 EVGA GTX750Ti,操作系统为 macOS Sierra 10.12.2 和 Windows 10 1607。

选择 GTX750Ti 的原因是,Akitio Thunder 2 本身无法提供供高功率显卡使用的额外 6pins/8pins 电源。与此同时,由于 Akitio Thunder 2 自带的电源适配器最大功率仅为 60W,同时为了支持 Thunderbolt 菊花链,官方宣称最大仅能为 PCI-E 插槽提供 25W 功率。实际上若不使用菊花链扩展,大概仅能有 40W 左右的功率是提供给显卡的,也是远远达不到标准的 75W PCI-E x16 插槽供电。若仅使用 Akitio Thunder 2 的原装电源适配器,在 GTX750Ti 高负载工作时就会失去响应造成系统卡死或者在开机时无法识别。因此笔者是采用自购的 120W 电源适配器为 Akitio Thunder 2 本身及显卡供电。若需要使用需求额外供电的显卡,要么购买自身带有额外供电功率的 Thunderbolt 盒子,要么就需要自行改造一个供电设备例如台式机使用的电源。关于这方面的说明网络上很多可自行查阅。

下文会对 macOS Sierra 和 Windows 10 关于外置显示器和内建显示器的使用有更多的说明。

 

macOS

首先要说明的是,经过数次的尝试,RMBP15 无法在不连接外置显示器的情况下将游戏画面用外置显卡渲染并传输回内建显示器。此外,在使用外置显示器的情况下(连接于外置显卡),游戏画面仅在外置显示器上能流畅输出,更具体的说明在下文会指出。此外,Nvidia 的 Kepler 系及 Maxwell 系显卡及 AMD Polaris 系及 Fiji 系显卡会被支持,其他显卡的支持情况笔者并不十分确定,需要参考 golaque 的说明(下文会提及)。

在 macOS 系统默认情况下,将硬件安装妥当的 Thunderbolt 2 外置显卡插入 RMBP15 是不会有响应的,因为系统需要一些修改及驱动的修改和安装。这里我们使用由 golaque 编写的 automate-eGPU 脚本可以方便的部署。该脚本的地址为 https://github.com/goalque/automate-eGPU

在使用该脚本前,RMBP15 需要将 System Integrity Protection (SIP) 关闭。开机按住 CMD+R 进入 Recovery OS 后打开终端执行 csrutil disable 后重启便可关闭 SIP。回到桌面环境后,连接 Thunderbolt 外置显卡(仅在未部署脚本前可热插拔),下载  automate-eGPU.sh 并执行,根据提示完成安装后保持外置显卡连接并重启即可在外置显示器上看到经由 Thunderbolt 外置显卡的输出画面了。部分设备还需要重新执行 automate-eGPU.sh -a 安装外置显卡守护程序,笔者的 RMBP15 和 Akitio Thunder 2 不需要因此在此不对该模式有更多说明。若要卸载该驱动及还原系统修改,执行 automate-eGPU.sh -uninstall 脚本即可。另外,若不在乎系统安全性建议不要重新开启 SIP,当然不妨可以尝试性开启或者尝试开启除了 kext 验证之外别的 SIP 保护(csrutil enable --without kext)。

在启用外置显卡后,若要让游戏由外置显卡来渲染,需要将主显示器设置为连接在外置显卡上的外置显示器,并将游戏窗口置于外置显示器内。设置主显示器的方法是在【系统偏好设置>显示器>排列】,将白色的条拖到需要设置为主显示器的窗格上去即可。如图所示:

笔者在网络上有看到一些消息说若需要使用内建显示器显示由外置显卡渲染的游戏画面,需要关闭【系统偏好设置>Mission Control>显示器具有单独的 Spaces】,并将游戏从外置主显示器拖回内建显示器。笔者尝试过该方法但很遗憾无法让 CS:GO 及 Dota 2 流畅运行,每秒帧数急剧下降,甚至低于仅使用内置显卡。若有需要不妨尝试一下,可以参考这篇文章 https://egpu.io/how-to-egpu-accelerated-internal-display-macos/

此外,在连接 Thunderbolt 外置显卡时请勿热插拔,插拔外置显卡都需要关机进行。

外话:在含有 Nvidia Geforce GT750M 的 RMBP15 上,使用 Nvidia Web Driver 并且不使用外置显卡时,若经由机身的接口连接外置显示器,GT750M 的闲置时最低功耗会保持在 16W 左右不论是否盒盖(关闭内建显示器),若要恢复到正常的闲置功耗(大概 5W)需要在盒盖后睡眠并唤醒一次。在不使用 Nvidia Web Driver 时,若盒盖,GT750M 会直接降低到 5W 左右的闲置功耗。当然若不盒盖(启用内建显示器),闲置时最低功耗都会保持在 16W 左右。

 

Windows

在 Windows 环境下,若不需要使用内建显示器显示由外置显卡渲染的画面就很简单了。在关机状态下插入 Thunderbolt 外置显卡并使用 EFI 模式启动的 Windows 10 可以直接识别外置显卡,安装驱动并重启后,将在连接于外置显卡上的外接显示器设为主显示屏即可流畅的运行游戏。并且由于省去了将画面传输回内建显示器的带宽,外置显卡可以更好的发挥性能。

若外置显卡为 Nvidia 的,若最新版的 Nvidia 显卡驱动无法安装,根据显卡型号可以尝试版本号介于 361.75 到 372.70 之间的版本。

若要使用传统的 MBR 方式引导 Windows 则可能用得到 DIY eGPU Setup 这个软件,软件地址为 https://egpu.io/diy-egpu-setup-1-30-nando4/。由于笔者不使用 MBR 引导,这个软件的效果及使用方式在此也不多作说明。

若需要使用内建显示器显示由外置显卡渲染的画面,若 RMBP 不具备内置的独立显卡或者在 BootCamp 下 CPU 核芯显卡未被屏蔽,应该是可以直接启用 Nvidia 的 Optimus 技术(笔者未经实机测试并不十分确定)。至于 AMD 外置显卡,不论是否具备内置的独立显卡,笔者并不十分确定是否可以使用使用内建显示器显示由外置显卡渲染的画面。若可以欢迎告诉我,若不可以也可参考下文的内容尝试开启。

在 BootCamp 环境下,若 RMBP 具有独立显卡,其 CPU 核芯显卡可能会被屏蔽,例如笔者的 RMBP15 的 Iris Pro 5200 在 Windows 中就不会被发现。因此,根据 https://github.com/0xbb/gpu-switch,若要启动核芯显卡,需要在系统引导前欺骗 RMBP 让其认为是在引导 macOS 而不是 Windows。通过 https://github.com/0xbb/apple_set_os.efi 可以实现这个效果。

要加载 apple_set_os.efi,需要在开机引导阶段使用 rEFInd。有两种安装 eEFInd 的方法:第一种是,首先需要关闭 SIP,然后前往 rEFInd 官方网站 http://www.rodsbooks.com/refind 根据官方文档安装 rEFInd 并需要修改 rEFInd 的配置,配置文件通常位于 /EFI 分区/EFI/refind/refind.conf;第二种是,不需要关闭 SIP,使用磁盘工具分出一个大约 100MB 的 MS-DOS(FAT) 格式分区,如图中的 REFIND 分区:

然后从 http://www.rodsbooks.com/refind/getting.html 下载 binary zip file 来手工安装 rEFInd,将 rEFInd 解压到新建出来的分区并放置到如图所示的文件夹中(需要放在 /新建分区/EFI/Boot/ 里),对于多平台支持部分注意仅需要 *_x64 的部分:

在第一种方法中,若安装 rEFInd 后无法在开机时显示 rEFInd 界面,或者 NVRAM 的默认引导程序被意外修改,则需要手工指定 NVRAM 的默认引导程序。在关闭 SIP 的情况下,在终端执行 diskutil mount /dev/disk0s1 && sudo bless --mount /Volumes/EFI --setBoot --file /Volumes/ESP/efi/refind/refind_x64.efi --shortform

接下来需要将 apple_set_os.efi 放在 /EFI 分区/EFI/custom/(安装方法一)或 /rEFInd 分区/EFI/custom/(安装方法二)文件夹内,例如 /EFI 分区/EFI/custom/apple_set_os.efi。设置完成后,重启,若使用方法一安装应直接出现 rEFInd 界面,若使用方法二安装需要按 Option 选择 rEFInd 分区启动 rEFInd(此时先不要连接外置显卡)。在 rEFInd 菜单中选择 apple_set_os.efi 所在的选项,按下回车执行,然后系统会重新返回到 rEFInd 界面,再选择 Bootcamp 分区启动 Windows 即可。此时,Windows 应该就可以发现核芯显卡并为其安装驱动即可(每次需要激活核芯显卡的时候均需要执行 apple_set_os.efi)。

在启用核芯显卡后,在 Windows 设备管理器内可以看到核芯显卡和内置独立显卡(第一次使用核芯显卡需要安装驱动),例如笔者的 RMBP15 拥有 Iris Pro 5200 及 Nvidia Geforce GT750M 都会显示在这。此时,内建显示器的画面仍是经由内置独立显卡进行渲染的。为了将内建显示器交由核芯显卡进行渲染,需要使用由 0xbb 编写的 gpu-switch 进行切换。打开 https://github.com/0xbb/gpu-switch 并下载 Windows 版本程序,为了下文方便在此将该程序放置到 C 盘根目录下新建的一个名为 gpu-switch 的文件夹内(C:\gpu-switch\),要切换到核芯显卡以管理员身份执行 integrated.bat 后重启生效,若要切换到内置独立显卡以管理员身份执行 dedicated.bat 后重启生效。在此,为了使用 Optimus,以管理员身份执行 integrated.bat,但是先不要重启。因为若同时启用核芯显卡、内置独立显卡以及外置显卡,RMBP15 无法正确的为外置显卡分配资源。因此需要把内置独立显卡禁用以将资源分配给外置显卡(但是可以在系统启动后,在资源已经分配给外置显卡的情况下,重新启用内置独立显卡)。接着重启后就会在桌面右键菜单中同时显示【英特尔显卡设置】选项和【NVIDIA 控制面板】选项,同时右下角会有由 Nvidia 驱动程序提供的图标以查看当前有应用启用了高性能显卡。进入游戏测试,此时应该就可以流畅的使用内建显示器显示由外置 Nvidia 显卡渲染的画面。

以上为基础的使用,但是有一些注意事项。首先,在 Windows gpu-switch 的程序切换显卡后,其效果并不能保持。若在切换到 macOS 后,其效果会消失。在 Windows 启动之后,若不重新执行切换,下次启动后效果也会消失。由于此前禁用了内置独立显卡,因此再次启动到 Windows 时,显示器画面会卡住在 Windows 启动界面,但其实此时系统并未卡住。此时若有开启播放 Windows 启动声音,应会听见启动声音,若有开启自动登录,在系统自动登录后按音量调节键会听到提示音,以此可以判断系统是否卡住。但是此时画面依然是卡住的。若没有外置显示器,在此急救方式是在一开机时按住 Option 进入 Apple 的启动磁盘选择界面选择 Windows 启动以避开 rEFInd 的修改让系统不识别到核芯显卡,或者连续重启 3 次 Windows,让其进入恢复模式后重启,或者更进一步进入安全模式重新启用内置独立显卡后重启,应该就可以恢复画面显示了。

因此,需要让系统在开机和关机的时候执行一些任务,以解决这个问题。在开机后,需要让系统启用被禁用的内置独立显卡。关机前,需要让系统禁用内置独立显卡以让未来插入的外置显卡有优先的资源分配权。在这需要使用到 DevManView 这个程序以方便的使用命令行快速启用或者禁用设备,可以在 http://www.nirsoft.net/utils/device_manager_view.html 下载。为了下文方便在此将该程序放置到 C 盘根目录下新建的一个名为 DevManView 的文件夹内(C:\DevManView\)。在运行中输入 gpedit.msc 打开组策略管理,展开到【计算机配置>Windows 设置>脚本(启动/关机)】,在【启动】属性>【脚本】选项卡中添加脚本路径C:\DevManView\devmanview.exe,参数为/enable "NVIDIA GeForce GT 750M",在【关机】属性>【脚本】选项卡中添加脚本路径C:\DevManView\devmanview.exe,参数为/disable "NVIDIA GeForce GT 750M"(在此,需要将 NVIDIA GeForce GT 750M 替换为你的内置独立显卡设备名称,可以在 DevManView 程序内查看)。

由于 gpu-switch 的效果不能保持,因此笔者选择在组策略的【启动】脚本内加入【C:\gpu-switch\gpu-switch -i】以保证系统能够在下次启动的时候切换到使用核芯显卡渲染内建显示器(【关机】脚本中是否也加入切换设置根据实际情况,非必需)。此外,若需要休眠电脑,推荐在【计划任务】内新建一条项目让系统在每次解锁用户后也执行一次显卡切换以保证系统能够在下次启动时使用核芯显卡渲染内建显示器。

此外,在任务管理器可能会发现 CPU 核心 0 的占用率一直保持在 100% 左右。若根据上文设定,在由 macOS 第一次切换到 Windows 后,内建显示器画面由内置独立显卡渲染,核芯显卡处于已发现未使用状态,CPU 核心 0 的占用率就会一直保持在 100% 左右,在此情况下笔者未找到可以修正 CPU 占用率的方法。但是在启动 Windows 后,使用 gpu-switch 切换到核芯显卡并重启 Windows,此时内建显示器画面变为由核芯显卡渲染,核芯显卡处于使用中状态,在此情况下,通过 Windows 设备管理器禁用并启用核芯显卡两次可以解决 CPU 占用率问题。因此,笔者选择在组策略的【启动】脚本内加入两行C:\DevManView\devmanview.exe /disable_enable "Intel(R) Iris(TM) Pro Graphics 5200"命令让系统在启动后自动重启两次核芯显卡(此处的 Intel(R) Iris(TM) Pro Graphics 5200 需要修改为你的核芯显卡设备名称,可以在 DevManView 程序内查看)。

在此,每当 RMBP 需要在 Windows 下使用外置显卡玩游戏时,只需要重启到 Windows>关机>插上外置显卡>开机,即可。

另外,经过笔者尝试,若已经切换到使用核芯显卡渲染内建显示器,在不使用外置显卡的情况下,无法使用内置的独立显卡对游戏进行处理(无法正常激活 Optimus,即使看上去设定是支持的,通过 GPU-Z 可以观察到实际上游戏仍由核芯显卡渲染)。若需要使用内置独立显卡渲染游戏,在一开机时按住 Option 进入 Apple 的启动磁盘选择界面选择 Windows 启动以避开 rEFInd 的修改让系统不识别到核芯显卡即可。

 

其他问题

有时候,在插上外置显卡时,Windows 会卡在启动界面,或者甚至连 RMBP 都无法启动(没有显示 rEFInd 或者不能听到“咚”的启动音),可能原因是由于 Akitio Thunder 2 的电源不能正确启动。多试几次移除 Thunderbolt 2 连接和断开 Akitio Thunder 2 电源,等待 Akitio Thunder 2 主板指示灯完全熄灭后重新连接电源,再重新连接 Thunderbolt 2 并开启 RMBP,一般来说可以解决。或者可以试试对调一下 Thunderbolt 线缆的两端。有几次笔者遇到这样的情况,尝试了无数次依然不能解决,最后重新启动到 macOS 后再重新切换到 Windows 才能解决,有点玄学的感觉。

在 Windows 关机时,笔者的 RMBP有很大几率无法断电(在画面消失后键盘灯依然亮着,风扇有可能还有可闻的噪音,外置显卡也未断电),或者需要等超出正常所需的时间才能断电。重启的情况也类似。笔者猜测是 ACPI 电源方面的问题,且不知道如何解决,一般等待一段时间后就手动强制关机了。

 

总结

对于非官方支持的外置显卡连接,很难做到尽善尽美,需要花费一定的时间和精力去折腾。随着 Thunderbolt 3 的大潮,笔者希望外置显卡可以更多的被应用,门槛也可以逐渐降低,也可以更加稳定顺心的使用。

 

放一些笔者微博的分享:

http://weibo.com/1751182302/EcGj0wtYv

http://weibo.com/1751182302/DAVFXkUt4

http://weibo.com/1751182302/DyATyyaDD

Posted in Notes.

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此页面链接二维码
QR: Macbook Pro (Retina, 15-inch, Late-2013) 外置显卡经验分享”/></br>

		
	</div><!-- #content .site-content -->

</div><!-- #primary .content-area -->


<div id=