公司动态
反射内存卡实战指南:以GE 5565系列为例的选型、部署与调优
反射内存卡这个东西做过分布式实时系统的人基本都绕不开。它解决的问题非常具体多个计算节点之间需要共享同一份数据而且这个共享必须满足微秒级延迟、确定性抖动、不依赖软件协议栈。GE 5565系列反射内存卡包括PCIE-5565PIORC-200000、PMC5565、VMIC5565这些常见型号就是为此设计的一类硬件。它最核心的价值不是带宽而是“写本地内存就是写所有节点内存”这种透明共享模型。本文不从官网参数说起而是按实际落地顺序讲清楚它解决什么问题、型号怎么选、单节点怎么跑通、多节点怎么同步、性能怎么验收、故障怎么排查。1. 反射内存卡解决的核心问题实时通信为什么需要共享内存1.1 它到底做什么先建立一个最小模型反射内存卡的运作方式第一眼看到会觉得很简单每台主机插一块卡卡上带有本机帧存储或板载内存多块卡之间通过光纤或铜缆组成一个网络。应用程序把要共享的数据写到本地卡的映射地址空间硬件逻辑自动把这个写操作发送到其他节点的卡上并且写入对应偏移地址。对上层应用来说它看到的不是一条网络链路而是一块所有节点都能直接读写的分布式共享内存。这个模型和“用TCP/IP在多台机器之间传数据”完全不同。反射内存没有协议栈的封装和解封装没有内核协议处理没有网卡中断调度的随机性。一个节点写入的延迟主要是硬件链路传播、对端内存写入、以及主机总线访问这三部分的叠加。而这三个部分都由硬件逻辑和专用协议控制不受软件调度影响所以延迟可预期。很多人第一次接触反射内存会问“这和共享文件夹有什么区别”区别在于共享文件夹的最终一致性是秒级甚至分钟级普通网络文件系统还要考虑缓存和锁。反射内存的一致性窗口是微秒量级而且所有节点几乎同时看到同一份数据。它适合的是分布式实时仿真、多机数据采集同步、半实物仿真、工控多控制器协同这类场景。1.2 和以太网、单机共享内存的差异在哪单机多进程共享内存性能很好但只在一台机器内。以太网能跨机器但普通以太网卡处理一个包要经过驱动、协议栈、中断、内存拷贝等多个环节延迟通常在几十微秒到几十毫秒之间波动抖动很难控制。反射内存卡恰好补上“多机 确定性低延迟 类共享内存接口”这段空白。用表格看更直观通信方式跨机器延迟量级抖动软件负担适用场景单机共享内存不支持纳秒到微秒低较低单机多进程普通以太网UDP支持亚毫秒到毫秒高高文件、流、非实时业务反射内存支持微秒级低低多机实时同步这不是说反射内存一定比以太网“高级”而是它在实时同步这个特定维度上更稳。做运动控制、飞行仿真、雷达数据拼接、多柜体同步采集时系统往往不能接受“偶尔慢一次”哪怕这个慢只出现0.1%。把数据访问变成内存读写至少减少了软件层面的不确定性。1.3 适合谁看这篇文章适合这么几类人刚拿到5565系列板卡正要开始调通的开发人员做分布式仿真或测控系统选型想搞清楚反射内存是不是必要方案的工程师还有已经用过一段时间卡在设备识别、延迟波动、数据不一致这些问题上的人。我建议先不要急着背型号而是先确认自己的实时性需求。如果系统里所有节点对数据延迟的容忍度都是毫秒级以上普通以太网加实时协议就够了。如果有一两个节点要求微秒级同步且数据量不大、偏状态类同步反射内存才是合适的候选。2. 5565系列选型PCIE-5565PIORC、PMC5565、VMIC5565怎么区分2.1 型号和总线形态的关系5565系列并不是只有一个型号。看到PCIE-5565PIORC-200000、PMC5565、VMIC5565这些名字时不要把它们理解成不同代际的产品它们更多是接口形态、物理规范和产品线来源上的区别。VMIC是较早的反射内存产品线后来并入GE相关产品序列所以VMIC5565这个名字在很多老项目里出现代表基板反射内存卡这一代体系。PMC5565是PMC尺寸的模块适合插在带PMC插槽的载板上常见于嵌入式单板计算机或军用抗恶劣环境计算机。PCIE-5565PIORC-200000从型号看是PCIe接口形态的反射内存板卡适合现代服务器、工业PC和相对标准化的机箱。我见过不少项目选型时只盯着“功能一样”就去下单结果到了现场发现机箱里根本没有对应总线插槽或者PMC载板的供电、后I/O方向对不上。功能定位相同不代表物理形态能互换。这块板卡是PCIe x1还是x4、PMC是否支持后走线、前面板是光纤口还是铜缆口都要以完整型号和厂商手册为准。2.2 选型前必须确定的六件事我在实际项目中一般会按下面这个顺序核对缺一项都可能影响落地主机总线类型PCIe、PCI、PMC、VME还是紧凑PCI。先确认机箱插槽规格包括5V/3.3V、辅助供电、物理尺寸。节点数量这套反射内存网络里总共接几块卡。有些场景是两块卡点对点有些是十几块卡组成环形或星形网络。节点数决定拓扑设计和端口数量。共享内存容量板载SDRAM或SRAM容量决定应用层能布置多大的共享数据区。如果每个节点要交换几十MB状态数据容量不够就得换别的方案或调整数据布局。传输介质光纤和铜缆各有利弊。光纤距离远、抗干扰强铜缆连接简单适合机柜内短距离。操作系统和驱动支持Windows、Linux、VxWorks、RTX等系统下的驱动能力不同。尤其做半实物仿真时系统可能是多个异构操作系统要确认每一边都有对应驱动。实时性预算提前定好允许的最大延迟和最大抖动不要等到联调时才拍脑袋。反射内存一般都在微秒级但不同拓扑、不同负载下的表现需要实测确认。2.3 容量、节点数和拓扑的取舍选型时最容易纠结的是“到底买多大容量”。我的判断标准是把需要共享的所有数据结构列出来统计最大占用空间再留出20%到30%余量。反射内存共享区不是磁盘不是越大越好因为板载内存大小直接对应硬件成本和复杂度。如果共享数据中包含大块图像或采样波形建议把这类数据放到低速存储区或另行使用高带宽链路反射内存更适合存放控制字、状态字、坐标、姿态、时间戳、关键事件这类小但要求严格同步的数据。拓扑方面两块卡最简单的形式是点对点。多块卡时可以环形连接也可以使用交换机或特定节点做中心汇聚。环形拓扑节约端口坏了一个节点可能导致断环需要看板卡是否支持直通旁路星形拓扑更容易扩展但中心设备可能成为单点。拿到板卡后建议先看完整产品说明书里的拓扑图再决定怎么布线。别先根据网上零散资料假设自己的板卡一定支持某种模式。3. 安装部署从硬件插槽到驱动加载3.1 上机前的检查项板卡到手后我建议先做一次最小系统验证不要直接插到满是GPU、RAID卡和采集卡的机箱里。最小系统是指一块主板、一个电源、一张反射内存卡最多加一块显示卡。这样做的好处是一旦出现设备不识别能快速排除总线冲突。硬件检查首先要确认插槽类型。PCIe接口的卡要看金手指型号和挡板高度插到不匹配的插槽会烧卡或者接触不良。PMC模块要先确认载板规格有的载板同时支持PMC和XMC引脚定义不同插错位置轻则识别不到重则短路。上电前还要确认时钟和电源。PCIe设备由系统提供参考时钟如果主板把同一个时钟源分给很多设备而某块卡的布线或负载有问题可能导致链路训练失败。这种问题在设备管理器或系统日志里往往表现为“没有探测到PCIe设备”但排查起来很麻烦。所以我会建议先换一个PCIe插槽验证尤其要避开和高速存储卡紧邻的槽位。3.2 驱动、固件和节点ID配置驱动安装顺序比很多人想的更重要。先装驱动再插卡还是先插卡再装驱动不同厂商有不同的推荐流程。反射内存卡不像普通USB设备那样一定是即插即用有些板卡需要在驱动安装完成后重启系统才会做完整的资源分配。节点ID是每一个使用5565系列板卡的人都必须理解的概念。反射内存网络里的每块卡在启动时要有唯一的节点标识通常通过卡上的拨码开关、软件配置工具或驱动参数设置。节点ID决定了这块卡在共享网络里的身份也对地址映射有影响。如果两块卡配成同一个ID轻则同步异常重则数据冲突。在正式接线之前先把每一块卡的节点ID记录下来并写在机箱标签上。固件版本同样值得检查。有的板卡出厂后固件支持两种传输介质切换但驱动需要对应版本。升级驱动和固件时一定要先看厂商发布说明里的版本匹配关系。我踩到过一次驱动换到了新版本固件还是旧的板卡能识别但中断一直不来后来把固件也升上去才正常。3.3 如何确认板卡已被正常枚举在Linux系统下最简单的做法是用lspci查看设备列表确认反射内存卡的vendor ID、device ID已经出现。用dmesg或journalctl看驱动加载日志确认没有地址冲突、中断申请失败之类的报错。在Windows系统下设备管理器里如果出现未知设备或者带感叹号的PCI设备说明枚举或驱动没有完成。这只是第一步。设备被枚举出来不等于链路已经同步。接下来要检查链路状态一般厂商工具或驱动会提供状态寄存器读取接口可以看到本板卡是否检测到光模块、对端是否在线、链路是否已经建立。这里有一个常见误区只看到设备管理器里没有感叹号就开始写应用程序结果读写共享内存时数据不更新最后才发现光纤根本没插好或者对端没有上电。我建议按照这个顺序完成首次验收单块卡上电确认驱动加载成功。读取本卡节点ID和状态寄存器。用厂商自带自检工具做本机回环测试。接第二块卡确认link状态。再进入应用层数据读写。4. 数据读写与多节点同步最少代码跑通4.1 反射内存的编程模型使用反射内存卡核心编程模型是把卡上的板载内存映射到用户空间然后像访问普通内存一样访问它。映射方式一般有两种一种是厂商提供封装好的API比如打开设备、按偏移读写数据、触发中断、读取状态。另一种是驱动把设备的BAR空间或内部内存直接映射到用户空间地址应用程序拿到映射基地址之后通过指针加偏移来读写。从效率角度我更喜欢第二种方式。因为反射内存的高价值在于“把我想要的数据放到地址上硬件自己去同步”如果用API一层层封装中间多了函数调用和可能的内存拷贝延迟优势会被削弱。当然具体能用哪种方式取决于厂商驱动和板卡支持程度。关键点在于所有节点访问的是同一块逻辑共享区。节点A往偏移0x100写入一个32位值节点B从自己卡上的映射地址偏移0x100读到的就是同一个值。偏移地址不需要区分“对方的IP地址”或者“对方的共享内存地址”它是一块全局统一编址的内存。4.2 一个最小的读写示例下面给出一段极简的示意代码重点不是精确的API而是理解流程/* 示意代码具体函数名以厂商SDK为准 */ rm_handle_t dev rm_open(0); if (!dev) { /* 记录日志并退出 */ } /* 映射本地卡的反射内存 */ void *base rm_map(dev, 0); if (!base) { /* 映射失败处理 */ } /* 向偏移0x100写入一个32位数据 */ *(volatile uint32_t *)((char *)base 0x100) 0xA5A5A5A5; /* 从同一偏移读取 */ uint32_t val *(volatile uint32_t *)((char *)base 0x100); rm_unmap(dev, base); rm_close(dev);这段代码在单节点上验证时写入后马上读回来值一致是正常的。但它还不能证明多节点同步有效。正确的方式是在节点A上写一个模式在节点B上读或者让节点B检测到偏移变化后回写一个确认值节点A再来读形成一个闭环验证。很多初学者在这里会犯一个错误只在单机上读写看到数据一致就认为链路正常。实际上单机读写只验证了本地映射和驱动的小部分功能完全没有验证光模块、对端节点和拓扑。4.3 多节点地址规划和数据一致性多节点运行后共享区不再是“一块随意读写的大内存”必须提前规划地址布局。我通常会把共享区划分成几类区域状态区每个节点各占一段固定偏移发布自己的状态、心跳、故障字。控制区主控节点下发命令其他节点读取。数据区存放坐标、时间戳、采样结果等周期性更新的数据。握手区存放序列号、计数器、事件标志。之所以要划分是因为反射内存网络虽然同步延迟低但它不是锁协议。多个节点同时往同一字节写最后的写入结果由硬件时序和最后到达的数据决定不保证“先到先赢”的多线程语义。为了规避竞争最好的办法是让每个节点只写自己的私有偏移区其他节点读取。比如节点1只能写0x0000到0x00FF节点2只能写0x0100到0x01FF以此类推。这样谁写坏了定位起来很清楚。数据一致性还要考虑序列号。如果节点A定期更新一个状态结构节点B靠周期性读取来获取最新值可能读到“前半部分是这一次更新后半部分是上一次更新”的拼接数据。解决办法是在结构体末尾加序列号每次整体更新后递增。节点B读取时先读序列号再读数据再读一次序列号如果前后一致才认为数据一致。4.4 中断、DMA和轮询方式怎么选反射内存卡一般都支持中断也知道触发中断的方式。一个节点写某个寄存器另一个节点可以收到中断从而唤醒应用层处理。这看起来很高效但在实时系统中我不建议把所有同步都压在硬件中断上。原因在于中断处理涉及上下文切换、中断优先级、CPU核调度等因素。在负载高的系统里中断响应时间也有抖动。对实时性要求极高的控制循环更好的方式是采用“轮询共享状态区里的更新标志或序列号”。轮询看起来会占用CPU但轮询周期可控确定性更强。在实时控制线程里每1毫秒或更短周期扫描一次关键偏移比被动等中断更稳。如果一定要用中断最好配合RTOS或实时补丁并手动绑定中断到指定的CPU核避免中断被其他任务延迟。同时要确认中断线没有与其他设备共享Linux下可以在中断配置里看affinity。5. 性能怎么看延迟、抖动、吞吐与验收方法5.1 先分清同步延迟和应用延迟性能验收时首先要分清两个概念同步延迟和应用延迟。同步延迟指的是一个节点完成向反射内存写数据到另一个节点从自己的反射内存地址读到这份数据这两者之间的时间差。这是反射内存硬件链路本身的性能。应用延迟则包含同步延迟之外的软件开销比如驱动调用、缓存刷新、任务调度、数据处理。如果板卡标称“微秒级同步”通常指的是链路同步延迟而不是应用程序从业务线程里发起到对端业务线程收到数据的完整时间。验收时不要用后者的测量结果去否定硬件本身更不要用一次测试就下结论。我的经验是先把硬件链路延迟测出来再逐步加入应用层代码看哪一层把延迟拉高了。5.2 实测步骤和判断标准可以按下面的步骤做一组基础测试单节点回环测试本地写本地读验证驱动和数据路径。双节点小包延迟测试节点A写一个更新标志并记录时间节点B轮询到变化后马上回写确认节点A收到确认后计算往返时间除以2得到单向延迟估算。抖动测试连续测几千次统计平均值、最大值、最小值和标准差。大包吞吐测试节点A从固定偏移连续写入几十KB到几MB数据节点B统计接收完成的数据块数和耗时。判断标准可以从这几个维度看延迟平均值落在什么范围是否符合项目实时性预算。抖动max减去min的值这个值对实时控制比平均值更重要。吞吐能否满足业务需要的最大数据量而不是追求理论峰值。稳定性连续运行几小时延迟有没有缓慢增长链路有没有重传或掉线。如果测试结果明显偏离预期不要急着把锅扣到环境上先检查测试代码本身。比如在测试函数里做了打印、日志、动态内存分配这些都会拉高延迟。测延迟的小包测试必须固定内存、关闭调试输出、锁定CPU核。5.3 哪些因素会让结果变差影响最终反映成“延迟变高”的因素常见有几类。第一类是主机总线问题。PCIe链路如果因为插槽冲突或主板布局而降速理论带宽虽然够但延迟和稳定会受影响。可以用系统工具读取PCIe链路速率确认它运行在预期状态。第二类是CPU调度。测试线程和使用线程如果频繁在核之间迁移缓存和中断绑定状态都会变化。要让实时线程锁核并避免和中断处理抢同一个核。第三类是数据写入模式。反射内存同步是按地址和长度组织的一次写入一小块数据和一次写入一大块数据硬件处理方式可能不同。如果你每个周期都写几十个零散偏移性能可能比集中写入一个连续块差不少。应用层里应该把该合并的小数据合并成一个结构体一次性写入。第四类是介质问题。光纤跳线脏污、收发模块兼容性差、距离超过规定值都会造成误码率上升和重传。表现为延迟不稳、偶发数据错。先清洁接口再换模块验证。表格总结指标含义建议测试方法单向延迟写方提交到读方可读的时间双节点回环除以2抖动延迟最大最小值之差连续测量多次吞吐单位时间内成功传输的数据量大块连续写入统计稳定性长时间运行时指标是否漂移连续运行对比不同时段6. 典型应用分布式仿真、多机测控和工控协同6.1 分布式半实物仿真中的共享状态区半实物仿真系统里通常有模型机、视景机、IO机柜、数据记录机等好几类节点。模型机计算飞行器或车辆的实时运动参数视景机需要按相同节奏拿到位置和姿态IO机柜需要输出控制信号。如果每个节点之间单独建立网络连接且不说软件复杂度光是对齐各节点的“同一时刻数据”就非常麻烦。反射内存在这里作为共享状态区很合适。模型机周期性计算完一帧数据后把它写入共享区。视景机、IO机柜各自按自己的刷新周期读取。因为反射内存会同步所有节点所以只要模型机以固定周期更新其他节点看到的近似是同一份最新状态。当然严格意义上它不保证绝对同步采样时刻还需要系统在时间管理上配合但比各节点自己独立维护一份状态再互相定时同步要简单。6.2 多机数据采集的时序一致性多个采集站同时采集同一物理信号时每个节点会生成带本地时标的数据流。要在后续数据处理时把这些数据拼接成有效的事件序列就需要节点之间有一个统一的“时间观察点”。反射内存可以把跨节点的帧序号、触发标志和时基信息放到共享区让每个采集节点知道“哪些采样点和哪些全局帧对应”。这个场景里数据量通常很大但是需要共享的不一定是原始采样波形而是触发、时标、状态字。原始波形完全可以通过其他存储和网络链路传输。如果误把反射内存当成高速数据传输通道塞入大量原始数据反而可能挤占同步通道的吞吐和稳定性。6.3 工控多控制器协同里的使用边界在工控场景多个控制器之间需要共享“允许启动”“故障状态”“下一步动作”等状态字。有些系统需要快速互相感知对方状态并对联合设备的控制动作保持一致。反射内存可以作为多个控制器之间的快速状态总线。但要注意边界反射内存不是完整的工业安全协议。它没有内置对节点故障的自动降级处理没有校验强一致性的多主锁机制。两个节点同时写入同一个命令字最终谁生效取决于硬件时序业务层必须有明确的所有权划分。真正的安全联锁回路建议在应用层单独做心跳检测、超时判定和故障导向安全。6.4 应用层还要做的几件事即使反射内存硬件负责了数据同步应用层仍然要处理这些问题节点启动顺序。反射内存网络最好能容忍节点在不同时间上电但应用层要设计“未就绪节点不参与写共享区”的逻辑。节点掉线检测。每个节点在状态区里写周期心跳其他节点检测到心跳超时后进入降级策略。数据版本管理。共享区数据结构升级时要先铺一段兼容区避免不同版本固件在运行中冲突。日志和监控。把共享区写入次数、异常标志、重启记录写到独立日志方便故障定位。这些不是板卡功能但直接决定反射内存方案能不能长期稳定运行。7. 故障排查和经验边界从枚举失败到数据错乱7.1 PCIe设备识别与资源分配问题设备不识别是最常见的第一类故障。现象是系统启动后设备管理器或lspci列表里根本没有这块卡。先不要怀疑卡坏了按下面的顺序排查检查物理安装插槽类型、金手指是否插到底、固定螺丝是否过紧导致板卡变形。检查供电有些板卡需要辅助供电或者PMC载板供电能力不足。换一个槽位或重新插拔看能否恢复。确认PCIe链路训练如果链路训练失败设备不会出现在总线上。可以换到另一路PCIe Root Port的插槽验证排除主板该通道故障。查看BIOS设置PCIe插槽是否被禁用、加载Above 4G的解码选项是否影响BAR分配、是否需要检查PCIe link speed设置。这里不同主板差异很大以主板手册为准。查驱动和资源占用如果设备出现在lspci里但驱动加载失败用dmesg查看是BAR分配失败还是中断失败。有的问题看起来是设备识别不了实际是驱动版本和内核版本不匹配或者之前插过同型号卡后系统仍缓存了旧配置。先把设备完整卸载干净重启再单卡安装能避开很多奇怪的兼容问题。7.2 光纤链路和误码排查设备识别正常但数据不同步下一步查链路。光纤跳线方向插反是最常见也最容易被忽略的问题。反射内存光纤接口有的是双芯一收一发成对如果收发交叉接错光模块能亮但通信无法建立。请先看说明书上的接口定义确认每根跳线的TX和RX方向严格对应到对端。光模块和跳线要是用了不同规格也可能出现灯亮但误码率高的情况。怀疑链路质量时看链路状态寄存器或误码计数器光模块能点亮不代表链路质量合格。可以采用替换法把同一根跳线换到另一套正常工作的节点上测试能快速判断是线缆、光模块还是板卡问题。多节点环形拓扑里一个节点异常断电可能导致整个网络断环。排查时把所有节点都置于已知正常状态再一个一个接入网络观察链路建立情况。不要所有节点同时上电出了问题很难定位。7.3 数据不一致、字节序和缓存问题数据能同步但读出来是错值需要区分几类原因。先看偏移地址。节点A写到0x100节点B却从0x200读自然读不到。这类问题定位最快但多人协作时最容易犯。建议在共享区里定义头文件或接口文档明确每个偏移的用途。再看字节序。x86机器和PowerPC、ARM等不同架构默认字节序不同。如果直接把一个结构体写入共享区对端按不同字节序解析多字节字段读出来就是乱的。解决办法是定义明确的网络字节序或统一使用小端在写之前转换。然后看缓存一致性。映射方式如果允许CPU缓存可能出现“对端已经写入但本地CPU缓存里还是旧值”的现象。这类问题通常出现在没有正确使用驱动提供的映射属性时。使用反射内存卡之前先看驱动文档里对缓存属性或内存屏障的说明。应用程序在读写共享区时注意使用编译器访问标志避免编译器优化掉看似重复的读取或写入操作。最后看写者冲突。多个节点同时写同一个偏移没有应用层所有权划分最终结果不可控。这种不符合反射内存的设计模型不是硬件缺陷而是用错了。7.4 反射内存方案什么时候不要用反射内存不是万能的对它的边界要有清醒认知。数据吞吐量极大时例如持续传输视频流或海量图像普通高带宽网络或专用数据链路更合适。反射内存的设计重点在低延迟同步不是大吞吐文件搬运。不要因为它是共享内存就以为能当内存盘用。跨越大距离时光纤虽然能跑一定距离但超过板卡规定的距离上限信号质量会下降。多地部署且节点相距几十公里以上要考虑其他同步方案。节点数量非常多时也要谨慎。反射内存网络扩展性受硬件拓扑和地址空间限制加上一百个节点以后成本和故障率都会增加。大规模集群的确定性同步有很多专门的高性能网络方案可以用不一定要死磕反射内存。成本敏感且实时性需求只有毫秒级普通以太网加中间件往往足够。反射内存的采购成本、光纤建设成本、维护成本都不低项目立项时要算清楚不要为了“技术上更酷”选了超出需求的方案。7.5 落地前的几点经验最后说几条我自己在实际项目里的经验。第一先跑通最小系统再扩展功能。两块卡、一根光纤、一个示例程序把链路验证扎实再往上加节点。不要一上来就搭全系统否则任何一个环节出错都会让排查范围扩大到整个网络。第二节点ID、偏移地址、数据结构要形成文档。这个文档比代码注释更关键。反射内存网络一旦有多个团队协作没有明确的地址分配约束联调时会浪费大量时间。第三把共享区里的数据访问做成统一的基础访问层而不是让大家各写各的偏移。基础访问层负责字节序转换、序列号递增、写入权限校验。业务逻辑不要直接打散操作映射区否则代码维护会很快失控。第四性能验收要在典型负载下做不要在空载下自测。空载时任何方案看起来都很快真实负载下CPU、内存、总线都会抢资源。至少模拟业务线程、中断负载和存储写入同时运行时的场景测试结果才有参考价值。反射内存卡这类硬件的价值从来不是“换个高性能网卡”那么简单。它本质上是在多节点之间建立了一块确定性共享内存让实时系统可以把数据交互当成内存访问来设计。只要你理解了它的同步模型、地址规划、性能指标和应用边界5565系列这类板卡就很容易落地。反过来如果忽略这些前置条件再好的硬件也会被软件调用方式拖慢。