深度剖析iOS渲染

iOS App 图形图像渲染的基本流程:

1.CPU:完成对象的创建和销毁、对象属性的调整、布局计算、文本的计算和排版、图片的格式转换和解码、图像的绘制。

2.GPU:GPU拿到CPU计算好的显示内容,完成纹理的渲染, 渲染完成后将渲染结果放入帧缓冲区。

简单来说,CPU就像科学家要进行繁琐的计算、GPU就像小学生进行简单的1+1计算,但是 GPU是通过并行执行大量的线程来完成计算任务的。GPU的并行计算能力是CPU的几倍甚至几十倍,可以处理大量的数据和计算任务,提高计算效率和速度。所以GPU主要应用在图像处理中,因此,大多数CALayer的属性都是用GPU来绘制。

3.帧缓冲区(Frame Buffer)(双缓冲机制,不再赘述)

正常情况下,在当前屏幕显示的内容,由 GPU 渲染完成后放到当前屏幕的帧缓存区,不需要额外的渲染空间。我们知道 iPhone 的屏幕刷新率是 60Hz,也就是刷新一帧的时间是 16.67 ms, 每隔这段时间视频控制器就会去读一次缓存区的内容来显示。 

假如 GPU 遇到性能瓶颈,导致无法在一帧内更新渲染结果到帧缓存区,那么从缓存区读到的会是上一帧的内容,导致帧率降低界面卡顿。

4.视频控制器:用来读取Frame Buffer中的数据的,GPU开始会绘制后缓存里的画面,然后视频控制器读取完前缓存的画面, 就会去读取后缓存里的画面,然后GPU再去绘制前缓存里的画面。

以上简单介绍了下iOS图像渲染。

接下来我们进一步深入了解。。。。。

CPU和GPU是如何渲染的?

首先给出一张图:iOS的渲染流水线。

上述图像渲染流水线中,除了第一部分 Application 阶段,后续主要都由 GPU 负责,为了方便后文讲解,先将 GPU 的渲染流程图展示出来:

上图就是一个三角形被渲染的过程中,GPU 所负责的渲染流水线。可以看到简单的三角形绘制就需要大量的计算,如果再有更多更复杂的顶点、颜色、纹理信息(包括 3D 纹理),那么计算量是难以想象的。这也是为什么 GPU 更适合于渲染流程。

接下来介绍的是iOS的渲染流水线(渲染管道)

1.Application 应用处理阶段:得到图元

这个阶段具体指的就是图像在应用中被处理的阶段,此时还处于 CPU 负责的时期。在这个阶段应用可能会对图像进行一系列的操作或者改变,最终将新的图像信息传给下一阶段。这部分信息被叫做图元信息,通常是三角形、线段、顶点等。见下图海豚就很直观了。

2.Geometry 几何处理阶段:处理图元

进入这个阶段之后,以及之后的阶段,就都主要由 GPU 负责了。此时 GPU 可以拿到上一个阶段传递下来的图元信息,GPU 会对这部分图元进行处理,之后输出新的图元。这一系列阶段包括:

  • 顶点着色器(Vertex Shader):这个阶段中会将图元中的顶点信息进行视角转换、添加光照信息、增加纹理等操作。
  • 形状装配(Shape Assembly):图元中的三角形、线段、点分别对应三个 顶点、两个 顶点、一个 顶点。这个阶段会将 顶点 连接成相对应的形状。
  • 几何着色器(Geometry Shader):额外添加额外的顶点,将原始图元转换成新图元,以构建一个不一样的模型。简单来说就是基于通过三角形、线段和点构建更复杂的几何图形。

3.Rasterization 光栅化阶段:图元转换为像素

光栅化的主要目的是将几何渲染之后的图元信息,转换为一系列的像素,以便后续显示在屏幕上。

4.Pixel 像素处理阶段:处理像素,得到位图

我们得到了图元所对应的像素,此时,我们需要给这些像素填充颜色和效果。

经过光栅化阶段得到了图元所对应的像素,此时,我们需要给这些像素填充颜色和效果。所以最后这个阶段就是给像素填充正确的内容,最终显示在屏幕上。这些经过处理、蕴含大量信息的像素点集合,被称作位图(bitmap)。也就是说,Pixel 阶段最终输出的结果就是位图,过程具体包含:

  • 片段着色器(Fragment Shader):对屏幕像素点着色。
  • 测试与混合(Tests and Blending):检查图层深度和透明度,从而判断片段的前后位置,以及是否应该被舍弃,并进行图层混合。

总的来说:

iOS的渲染分为四个部分:

  • 应用处理阶段:相当于 CPU 执行的部分,负责处理逻辑并提交渲染指令。
  • 几何处理:负责几何变换和顶点处理,转化为图元。
  • 光栅化:将图元转化为片段,生成像素数据。
  • 像素处理:片段着色、纹理映射等,输出到帧缓冲区(Frame Buffer)。

位图:

位图(Bitmap) 是一种数据结构。一个位图是由 n*m 个像素组成,每个像素的颜色信息由 RGB 组合或者灰度值表示。见下图:

介绍完iOS渲染流水线后(其实这里介绍的就是App图像渲染的基本流程的CPU和GPU部分),我们回到图像渲染的基本流程,接下来我们要介绍有关垂直同步信号和双缓冲机制的内容。

如何将已经渲染好的图像放到屏幕上?

这里先简单介绍下屏幕成像的原理:

显示器的电子束会从屏幕的左上角开始逐行扫描,屏幕上的每个点的图像信息都从帧缓冲器中的位图进行读取,在屏幕上对应地显示。扫描的流程如下图所示:

这时候就会出现一个问题:我如何知道屏幕下一个位置的像素是否已经渲染好了并且已经存放在了帧缓存区里面(这就是我们说的屏幕撕裂的问题)?这里就涉及到了两个机制:

  • 垂直同步信号
  • 双缓冲机制

1.垂直同步信号

当电子束完成一帧的扫描,将要从头开始扫描时,就会发出一个垂直同步信号。只有当视频控制器接收到 Vsync 之后,才会将帧缓冲器中的位图更新为下一帧,这样就能保证每次显示的都是同一帧的画面,因而避免了屏幕撕裂。

简单来说就是:帧缓冲器接收到信号了,才更新下一帧。

2.双缓冲机制

所以双缓冲机制会增加一个新的备用缓冲器(back buffer)。渲染结果会预先保存在 back buffer 中,在接收到 Vsync 信号的时候,视频控制器会将 back buffer 中的内容置换到 frame buffer 中,此时就能保证置换操作几乎在一瞬间完成(实际上是交换了内存地址)。

简单来说就是:GPU开始会绘制后缓存里的画面,然后视频控制器读取完前缓存的画面, 就会去读取后缓存里的画面,然后GPU再去绘制前缓存里的画面。

通过双缓冲机制,我们可以在60FPS(16.67ms)前,置换新的一帧屏幕图像。这样就能及时的更新屏幕图像了,就能解决屏幕撕裂问题。

掉帧

但是,如果在接收到 Vsync 之时 CPU 和 GPU 还没有渲染好新的位图,视频控制器就不会去替换 frame buffer 中的位图。这时屏幕就会重新扫描呈现出上一帧一模一样的画面。相当于两个周期显示了同样的画面,这就是所谓掉帧的情况。

这时候我们可以用三缓冲机制来优化CPU和GPU的效率,也就是在CPU和GPU的空闲时间再渲染一个区域。

总的来说:

  • 屏幕卡顿的根本原因:CPU 和 GPU 渲染流水线耗时过长,导致掉帧。
  • Vsync 与双缓冲的意义:强制同步屏幕刷新,以掉帧为代价解决屏幕撕裂问题。
  • 三缓冲的意义:合理使用 CPU、GPU 渲染性能,减少掉帧次数。

上述我们介绍了iOS中将内容数据通过一系列渲染后放到屏幕的详细过程,接下来将会讲解iOS的渲染框架,iOS 提供了多个渲染框架,帮助开发者管理渲染流程中的各个步骤。

见下图:

GPU Driver:上述软件框架相互之间也有着依赖关系,不过所有框架最终都会通过 OpenGL 连接到 GPU Driver,GPU Driver 是直接和 GPU 交流的代码块,直接与 GPU 连接。

OpenGL:是一个提供了 2D 和 3D 图形渲染的 API,它能和 GPU 密切的配合,最高效地利用 GPU 的能力,实现硬件加速渲染。OpenGL的高效实现(利用了图形加速硬件)一般由显示设备厂商提供,而且非常依赖于该厂商提供的硬件。OpenGL 之上扩展出很多东西,如 Core Graphics 等最终都依赖于 OpenGL,有些情况下为了更高的效率,比如游戏程序,甚至会直接调用 OpenGL 的接口。

Core Graphics:Core Graphics 是一个强大的二维图像绘制引擎,是 iOS 的核心图形库,常用的比如 CGRect 就定义在这个框架下。

Core Animation在 iOS 上,几乎所有的东西都是通过 Core Animation 绘制出来,它的自由度更高,使用范围也更广。

Core Image:Core Image 是一个高性能的图像处理分析的框架,它拥有一系列现成的图像滤镜,能对已存在的图像进行高效的处理。

Metal:Metal 类似于 OpenGL ES,也是一套第三方标准,具体实现由苹果实现。Core Animation、Core Image、SceneKit、SpriteKit 等等渲染框架都是构建于 Metal 之上的。

我们可以看到,在iOS上,几乎所有的东西都是通过 Core Animation 绘制出来,接下来我们深入了解Core Animation。

Core Animation:

Core Animation,它本质上可以理解为一个复合引擎,主要职责包含:渲染、构建和实现动画。

Core Animation 是 AppKit 和 UIKit 完美的底层支持,同时也被整合进入 Cocoa 和 Cocoa Touch 的工作流之中,它是 app 界面渲染和构建的最基础架构。 Core Animation 的职责就是尽可能快地组合屏幕上不同的可视内容,这个内容是被分解成独立的 layer(iOS 中具体而言就是 CALayer),并且被存储为树状层级结构。这个树也形成了 UIKit 以及在 iOS 应用程序当中你所能在屏幕上看见的一切的基础。

简单来说就是用户能看到的屏幕上的内容都由 CALayer 进行管理。

CALayer 是屏幕显示的基础(存储 bitmap)

CALayer的简单构成:

在运行时,操作系统会调用底层的接口,将 image 通过 CPU+GPU 的渲染流水线渲染得到对应的 bitmap,存储于 CALayer.contents 中,在设备屏幕进行刷新的时候就会读取 bitmap 在屏幕上呈现。

也正因为每次要被渲染的内容是被静态的存储起来的,所以每次渲染时,Core Animation 会触发调用 drawRect: 方法,使用存储好的 bitmap 进行新一轮的展示。

CALayer 与 UIView 的关系

  1. CALayer 是 UIView 的属性之一,负责渲染和动画,提供可视内容的呈现
  2. UIView 提供了对 CALayer 部分功能的封装,同时也另外负责了交互事件的处理。

可得出其他关系:

相同的层级结构:我们对 UIView 的层级结构非常熟悉,由于每个 UIView 都对应 CALayer 负责页面的绘制,所以 CALayer 也具有相应的层级结构。

部分效果的设置:因为 UIView 只对 CALayer 的部分功能进行了封装,而另一部分如圆角、阴影、边框等特效都需要通过调用 layer 属性来设置。

是否响应点击事件:CALayer 不负责点击事件,所以不响应点击事件,而 UIView 会响应。

不同继承关系:CALayer 继承自 NSObject,UIView 由于要负责交互事件,所以继承自 UIResponder。

为什么要将CALayer和UIView分离开来?

将 CALayer 独立出来这样设计的主要原因就是为了职责分离,拆分功能,方便代码的复用。通过 Core Animation 框架来负责可视内容的呈现,这样在 iOS 和 OS X 上都可以使用 Core Animation 进行渲染。与此同时,两个系统还可以根据交互规则的不同来进一步封装统一的控件。

Core Animation的渲染流程:

(区别于前面讲的iOS渲染流流水线,两者均为iOS渲染基础但是服务的层次和方面不一样)

整个流水线一共有下面几个步骤:

Handle Events:这个过程中会先处理点击事件,这个过程中有可能会需要改变页面的布局和界面层次。

Commit Transaction:此时 app 会通过 CPU 处理显示内容的前置计算,比如布局计算、图片解码等任务,接下来会进行详细的讲解。之后将计算好的图层进行打包发给 Render Server

Decode:打包好的图层被传输到 Render Server 之后,首先会进行解码。注意完成解码之后需要等待下一个 RunLoop 才会执行下一步 Draw Calls

Draw Calls:解码完成后,Core Animation 会调用下层渲染框架(比如 OpenGL 或者 Metal)的方法进行绘制,进而调用到 GPU。

Render:这一阶段主要由 GPU 进行渲染。

Display:显示阶段,需要等 render 结束的下一个 RunLoop 触发显示。

深度了解Commit Transaction:

一般开发当中能影响到的就是 Handle Events 和 Commit Transaction 这两个阶段,这也是开发者接触最多的部分。Handle Events 就是处理触摸事件,而 Commit Transaction 这部分中主要进行的是:Layout、Display、Prepare、Commit 等四个具体的操作。

1.Layout:构建视图

这个阶段主要处理视图的构建和布局,具体步骤包括:

  1. 调用重载的 layoutSubviews 方法
  2. 创建视图,并通过 addSubview 方法添加子视图
  3. 计算视图布局,即所有的 Layout Constraint

由于这个阶段是在 CPU 中进行,通常是 CPU 限制或者 IO 限制,所以我们应该尽量高效轻量地操作,减少这部分的时间,比如减少非必要的视图创建、简化布局计算、减少视图层级等。

2.Display:绘制视图

这个阶段主要是交给 Core Graphics 进行视图的绘制,注意不是真正的显示,而是得到前文所说的图元 primitives 数据:

  1. 根据上一阶段 Layout 的结果创建得到图元信息。
  2. 如果重写了 drawRect: 方法,那么会调用重载的 drawRect: 方法,在 drawRect: 方法中手动绘制得到 bitmap 数据,从而自定义视图的绘制。

注意正常情况下 Display 阶段只会得到图元 primitives 信息,而位图 bitmap 是在 GPU 中根据图元信息绘制得到的。但是如果重写了 drawRect: 方法,这个方法会直接调用 Core Graphics 绘制方法得到 bitmap 数据,同时系统会额外申请一块内存,用于暂存绘制好的 bitmap。

由于重写了 drawRect: 方法,导致绘制过程从 GPU 转移到了 CPU,这就导致了一定的效率损失。与此同时,这个过程会额外使用 CPU 和内存,因此需要高效绘制,否则容易造成 CPU 卡顿或者内存爆炸。

3.Prepare:Core Animation 额外的工作

这一步主要是:图片解码和转换

4.Commit:打包并发送

这一步主要是:当 runloop 在 kCFRunLoopBeforeWaiting 和 kCFRunLoopExit 状态时,会通知注册的监听,然后对图层打包,打完包后,将打包数据发送给一个独立负责渲染的进程 Render Server。图层打包并发送到 Render Server。

注意 commit 操作是依赖图层树递归执行的,所以如果图层树过于复杂,commit 的开销就会很大。这也是我们希望减少视图层级,从而降低图层树复杂度的原因。

Render Server 的具体操作

Render Server 通常是 OpenGL 或者是 Metal。以 OpenGL 为例,那么上图主要是 GPU 中执行的操作,具体主要包括:

  1. GPU 收到 Command Buffer,包含图元 primitives 信息
  2. Tiler 开始工作:先通过顶点着色器 Vertex Shader 对顶点进行处理,更新图元信息
  3. 平铺过程:平铺生成 tile bucket 的几何图形,这一步会将图元信息转化为像素,之后将结果写入 Parameter Buffer 中
  4. Tiler 更新完所有的图元信息,或者 Parameter Buffer 已满,则会开始下一步
  5. Renderer 工作:将像素信息进行处理得到 bitmap,之后存入 Render Buffer
  6. Render Buffer 中存储有渲染好的 bitmap,供之后的 Display 操作使用

这里有张流程图总结的特别好:

以上就是iOS渲染的流程笔记。

 离屏渲染

离屏渲染发生在iOS的渲染流程中(CPU、GPU、双缓冲器、视频控制器、屏幕)。我们知道,图像处理基本上是在 GPU中进行的,而GPU屏幕渲染有以下两种方式:

1.On-Screen Rendering:当前屏幕渲染,指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行。

正常情况下,如果要在显示屏上显示内容,我们至少需要一块与屏幕像素数据量一样大的帧缓冲区(frame buffer),作为像素数据存储区域,而这也是GPU存储渲染结果的地方。

2.Off-Screen Rendering:离屏渲染,指的是GPU在当前屏幕缓冲区以外新开辟一个(离屏)缓冲区进行渲染操作。

如果有时因为一些限制,无法把渲染结果直接写入frame buffer,而是先暂存在另外的内存区域,之后再写入frame buffer,那么这个过程被称之为离屏渲染。

其实

离屏渲染是有坏处的:

1.需要开辟一个新的缓存区,影响app性能。

2.因为是新的缓存区,此时有两个缓存区,那么GPU就要进行上下文切换来分别渲染,而上下文切换的代价是巨大的,会导致掉帧甚至卡顿。

那么,什么时候会触发离屏渲染呢?

我们再回顾下面layer的简单构成:

对于特定图层效果的使用,比如圆角,图层遮罩,阴影或者是图层光栅化都会强制Core Animation提前渲染图层的离屏绘制(注意⚠️:一旦我们 为contents设置了内容 ,无论是图片、绘制内容、有图像信息的子视图等,再加上圆角+裁剪,就会触发离屏渲染,而当contens没有内容时,圆角和裁剪都不会触发离屏渲染)。也就是说,当layer的contens中有东西(图片,色彩等)时, GPU为了将所有该绘画的绘画完了,再去为这个“结果”添加阴影或圆角,那么就需要离屏渲染存储layer。也就是说:阴影的本体(layer和其子layer)都还没有被组合到一起,怎么可能在第一步就画出只有完成最后一步之后才能知道的形状呢?这样一来又只能另外申请一块内存,把本体内容都先画好。

至于优化的话,有以下几种解决方法:

1.缓存已经处理好的结果,然后在复用的时候再拿出来用,得用shouldRasterize, 但是这个会导致至少一次离屏渲染,不过相对于有许多layer都各离屏渲染一次,这样处理就优化很多了。如果你的layer本来并不复杂,也没有圆角阴影等等,打开这个开关反而会增加一次不必要的离屏渲染

2.贝塞尔曲线优化

推荐大佬文章Texture | Corner Rounding

参考:[转] iOS离屏渲染原理及优化 · Tenloy's Blog

Core-Animation(三) - 渲染流程探究及性能分析 · Tenloy's Blog

iOS 离屏渲染探究 - 掘金

https://github.com/RickeyBoy/Rickey-iOS-Notes/blob/master/%E7%AC%94%E8%AE%B0/iOS%20Rendering.md

渲染(iOS渲染过程解析)_ios渲染流程-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/425022.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

界面控件DevExpress中文教程:如何PDF图形对象的可见性?

DevExpress拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpress Dashboard eXpressApp 框架、适用于 Visual Studio的CodeRush等一系列辅助工具。屡获大奖的软件开发平台DevExpress 近期重要版本v24.1已正式发布,该版本拥有众多新产…

STM32与ESP8266的使用

串口透传 “透传”通常指的是数据的透明传输,意思是在不对数据进行任何处理或修改的情况下,将数据从一个接口转发到另一个接口。值得注意的是要避免串口之间无限制的透明,可以采用互斥锁的方式进行限制使用方法 对USART1和USART3(用他俩举例…

word文档无损原样转pdf在windows平台使用python调用win32com使用pip安装pywin32

前提: windows环境下,并且安装了office套装,比如word,如果需要调用excel.也需要安装。在另外的文章会介绍。这种是直接调用word的。所以还原度会比较高。 需求: word文档转pdf,要求使用命令行形式,最终发布为api接口…

基于高通主板的ARM架构服务器

一、ARM架构服务器的崛起 (一)市场需求推动 消费市场寒冬,全球消费电子需求下行,服务器成半导体核心动力之一。Arm 加速布局服务器领域,如 9 月推出 Neoverse V2。长久以来,x86 架构主导服务器市场&#…

QTreeView模糊查询

本文代码效果如下&#xff1a; 本文代码&#xff1a; https://download.csdn.net/download/Sakuya__/89759410https://download.csdn.net/download/Sakuya__/89759410 代码之路 MainWindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #incl…

基于Ant-Design-Vue设计的配置化表单

适用vue 3.4 版本以上 在日常的前端开发中&#xff0c;表单开发必不可少&#xff0c;尤其是在遇到一些大型的复杂的表单&#xff0c;这往往会变成一个痛点。于是就想着开发一个可以list来配置的表单组件。 先上组件代码 <!-- 该组件 VUE 版本在 3.4 以上可使用--> <…

【QT】定时器使用

文章目录 关于 Qt 定时器使用的注意细节总结实例-检查工具使用周期时间是否合理UI设计头文件 remind.h源文件 remind.cpp实现效果 关于 Qt 定时器使用的注意细节总结 一、创建与初始化 使用 QTimer 类来创建定时器。可以在构造函数中指定父对象&#xff0c;确保定时器在正确的…

JavaDS —— B树

前言 本章节将带领大家进入B树的学习&#xff0c;主要介绍B树的概念和B树的插入代码的实现&#xff0c;删除代码不做讲解&#xff0c;最后简单介绍B树和B*树。 B树的概念 1970年&#xff0c;R.Bayer和E.mccreight提出了一种适合外查找的树&#xff0c;它是一种平衡的多叉树&…

【制作100个unity游戏之32】unity开发属于自己的一个2d/3d桌面宠物,可以实时计算已经获取的工资

最终效果 文章目录 最终效果一、实现Windows消息弹窗二、将窗口扩展到工作区三、穿透能点击到其他区域四、模型交互1、我们可以新增ObjectDrag 代码控制人物拖拖动2、实现模型交互五、最终代码六、其他七、游玩地址七、源码参考完结一、实现Windows消息弹窗 参考:https://lear…

WEB打点

目录 web打点概述打点流程打点中的问题getshell手法汇总web打点批量检测端口扫描POC扫描指纹识别漏洞扫描 手工检测开源框架漏洞通用框架漏洞基础web漏洞商用系统漏洞 WAF绕过waf分类常见waf拦截界面WAF绕过思路侧面绕&#xff1a;适合云WAF直面WAF web打点概述 打点流程 资产…

QT模型视图结构2

文章目录 Qt 模型视图结构——模型类(二)1.基本概念1.1.模型的基本结构1.2.模型索引1.3.行号和列号1.4.父项1.5.项的角色 Qt 模型视图结构——模型类(二) ​ 模型/视图结构是一种将数据存储和界面展示分离的编程方法。模型存储数据&#xff0c;视图组件显示模型中的数据&#…

【AI赋能医学】基于深度学习和HRV特征的多类别心电图分类

一、数据集简介 论文中使用了来自三类不同心电图记录的162条数据&#xff0c;这些数据来自三个公开的数据库&#xff1a; MIT-BIH 心律失常数据库 (ARR) 96条记录&#xff0c;主要包含不同类型的心律失常样本。 MIT-BIH 正常窦性心律数据库 (NSR) 36条记录&#xff0c;包含健…

Gitlab实现多项目触发式自动CICD

工作中可能会遇到这种场景&#xff0c;存在上游项目A和下游项目B&#xff0c;项目B的功能依赖项目A&#xff08;比如B负责日志解析&#xff0c;A是日志描述语言代码&#xff09;&#xff0c;这种相互依赖的项目更新流程一般如下&#xff1a; A项目更新&#xff0c;通知B项目开发…

Unity中InputField一些属性的理解

先看代码&#xff1a; using UnityEngine; using UnityEngine.UI;public class TestInput : MonoBehaviour {[SerializeField]InputField inputField;void Start(){Debug.Log(inputField.text);Debug.Log(inputField.text.Length);Debug.Log(inputField.preferredWidth);Debug…

2024工业机器视觉产业现状

早在20世纪80年代美国国家标准局就预计&#xff0c;检测任务的80%乃至90%将由视觉测量系统来完成&#xff0c;该预测至今已基本变成现实。当前&#xff0c;以智能制造为核心的工业4.0时代背景下&#xff0c;新型工业化的战略部署逐步深入&#xff0c;伴随AI大模型技术应用的逐步…

泰语快速学习方法!速成方法学习!

要快速学习泰语&#xff0c;可以采取多种策略&#xff0c;如掌握基础语法和词汇&#xff0c;专注于发音练习以掌握泰语特有的音调系统&#xff0c;利用语言学习软件进行互动学习&#xff0c;通过观看泰语媒体内容提高听力理解&#xff0c;与母语者进行语言交换来锻炼口语&#…

I2C/IIC学习笔记

I2C/IIC 有些同学I2C和IIC分不清&#xff0c;I2C和IIC实际上是指同一种通信协议。I2C是Inter-Integrated Circuit的缩写&#xff0c;而IIC是它的另一种表述方式&#xff0c;代表的是同一个意思&#xff0c;即“集成电路间总线”。I2C是一种由飞利浦公司&#xff08;现恩智浦半…

python AssertionError: Torch not compiled with CUDA enabled

查看&#xff1a;torch import torch# 输出带CPU&#xff0c;表示torch是CPU版本的 print(ftorch的版本是&#xff1a;{torch.__version__}) # print(ftorch是否能使用cuda&#xff1a;{torch.cuda.is_available()}) 修改一下代码&#xff0c;将cuda改成cpu 最后运行正常&…

织物缺陷检测系统源码分享

织物缺陷检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

跨界融合,GIS如何赋能游戏商业——以《黑神话:悟空》为例

在数字化时代&#xff0c;地理信息系统&#xff08;GIS&#xff09;技术正以其独特的空间分析和可视化能力&#xff0c;为游戏产业带来革命性的变革。《黑神话&#xff1a;悟空》作为中国首款3A级别的动作角色扮演游戏&#xff0c;不仅在游戏设计和技术上取得了突破&#xff0c…