Unity 批处理详讲(含URP)

          咱们在项目中,优化性能最重要的一个环节就是合批处理,,在早期Unity中,对于合批的处理手段主要有三种:   

  • Static Batching 
  • Dynamic Batching  
  • GPU Instancing  

如今Unity 为了提升合批范围与效率,提供了新的合批方式(SRP Batcher)。 

   

      一:初识   Draw Call、Batcher、 Sat pass Call  

                                               衡量CPU处理渲染速率的参考值

    Draw Call

            衡量CPU在渲染时的资源消耗大多都是是通过Draw Call的数量 因为CPU在渲染流水线中的处理阶段是应用程序阶段,主要是做一些数据的准备与提交工作,而Draw Call的数量代表了CPU向GPU提交的数据的次数,Draw Call本身只是一些数据流的字节,主要的性能消耗在于CPU的数据准备阶段。

   Batcher

          由于合批的出现,并不会每一个渲染对象都会产生一个Draw Call,所以这个时候就提出了一个新的衡量标准:Batcher

   Sat pass Call  

         CPU在渲染阶段,性能消耗的峰值一般不在于Draw Call,而往往存在于对其数据准备的阶段,因此单纯以数据的提交数量为衡量标准并不准确,同时在数据准备的过程中,假如前后两个材质发生了变化,会更大幅度的消耗性能,这也是整个CPU在渲染阶段最消耗性能的步骤,因此Unity通过Set Pass Call来作为性能消耗的标准。   (注意:实际上并没有减少Draw Call

   二:主流合批技术详讲

    1、Static Batching

            原理:

                     

  • 将静态游戏对象转换到世界空间并为它们构建一个共享的顶点和索引缓冲区。
  • 如果已启用 Optimized Mesh Data,则 Unity 会在构建顶点缓冲区时删除任何着色器变体未使用的任何顶点元素。为了执行此操作,系统会进行一些特殊的关键字检查;例如,如果Unity 未检测到 LIGHTMAP_ON关键字,则会从批处理中删除光照贴图 UV
  • 针对同一批次中的可见游戏对象,Unity 会执行一系列简单的绘制调用,每次调用之间几乎没有状态变化。在技术上,Unity不会减少 API绘制调用,而是减少它们之间的状态变化(这正是消耗大量资源的部分)。在大多数平台上,批处理限制为 64k 个顶点和 64k 个索引(OpenGLES 上为 48k 个索引,在 macOS 上为 32k 个索引)

      简单的来说,Static Batching通过对一些小的网格进行合并备份到内存中,当执行渲染操作时,CPU一次性将合并的内存的发送给GPU来减少Draw Call的数量,不过这样做有一定的限制:

  • 对象必须是静态的,不可移动
  • 合并的对象使用相同的材质

同时在使用Static Batching时需要额外的内存来存储组合的几何体,导致内存在一定程度上的浪费。简单来说,作为通过内存的上的置换可以获得时间上的高效运行,需要根据实际情况来谨慎添加渲染对象,避免获取CPU性能优势时产生不必要的内存问题

而关于Static Batching的使用,首先需要在Project Setting中的Player选项中勾选Static Batching

      接下来就可以在Inspector面板中对需要Static Batching的对象勾选上Batching Static,具体位置如下图所示: 

      

  • 无法参与批处理情况
  1. 改变Renderer.material将会造成一份材质的拷贝,因此会打断批处理,你应该使用Renderer.sharedMaterial来保证材质的共享状态。
  2. 相同材质批处理断开情况
    位置不相邻且中间夹杂着不同材质的其他物体,不会进行同批处理,这种情况比较特殊,涉及到批处理的顺序。
    拥有lightmap的物体含有额外(隐藏)的材质属性,比如:lightmap的偏移和缩放系数等。所以,拥有lightmap的物体将不会进行同批处理(除非他们指向lightmap的同一部分)。

总结: 虽然静态合批可以有效地减少批次,但是可能无法减少DC。

 2、Dynamic Batching   

        Dynamic Batching同样是可以对于有共同材质的对象进行相关的合并,但是其对象可以为动态的,而且这一过程是动态进行的,只需要在Project Setting中的Player中勾选上Dynamic Batching即可,但是注意,在URP模板中,这一选项移到了URP的配置文件中,具体位置如图: 

  

虽然Dynamic Batching的设置简单,但是其使用条件却很苛刻,Unity官方在文档中详细罗列限制条件:

  • 批处理动态游戏对象在每个顶点都有一定开销,因此批处理仅会应用于总共包含不超过 900 个顶点属性且不超过 300 个顶点的网格。如果着色器使用顶点位置、法线和单个 UV,最多可以批处理 300 个顶点,而如果着色器使用顶点位置、法线、UV0、UV1 和切线,则只能批处理 180 个顶点。
  • 如果游戏对象在变换中包含镜像,则不会对这些对象进行批处理(例如,具有 +1 缩放的游戏对象 A 和具有 –1 缩放的游戏对象 B 无法一起接受批处理)。即使游戏对象基本相同,使用不同的材质实例也会导致游戏对象不能一起接受批处理。例外情况是阴影投射物渲染。
  • 带有光照贴图的游戏对象具有其他渲染器参数:光照贴图索引和光照贴图偏移/缩放。通常,动态光照贴图的游戏对象应指向要批处理的完全相同的光照贴图位置。 多 pass 着色器会中断批处理。
  • 几乎所有的 Unity 着色器都支持前向渲染中的多个光照,有效地为它们执行额外 pass。“其他每像素光照”的绘制调用不进行批处理。 旧版延迟(光照 pre-pass)渲染路径会禁用动态批处理,因为它必须绘制两次游戏对象

    

   批处理中断情况:
       位置不相邻且中间夹杂着不同材质的其他物体,不会进行同批处理,这种情况比较特殊,涉及到批处理的顺序,我的另一篇文章有详解。
物体如果都符合条件会优先参与静态批处理,再是GPU Instancing,然后才到动态批处理,假如物体符合前两者,此次批处理都会被打断。
GameObject之间如果有镜像变换不能进行合批,例如,"GameObject A with +1 scale and GameObject B with –1 scale cannot be batched together"。
拥有lightmap的物体含有额外(隐藏)的材质属性,比如:lightmap的偏移和缩放系数等。所以,拥有lightmap的物体将不会进行批处理(除非他们指向lightmap的同一部分)。
使用Multi-pass Shader的物体会禁用Dynamic batching,因为Multi-pass Shader通常会导致一个物体要连续绘制多次,并切换渲染状态。这会打破其跟其他物体进行Dynamic batching的机会。
我们知道能够进行合批的前提是多个GameObject共享同一材质,但是对于Shadow casters的渲染是个例外。仅管Shadow casters使用不同的材质,但是只要它们的材质中给Shadow Caster Pass使用的参数是相同的,他们也能够进行Dynamic batching。
Unity的Forward Rendering Path中如果一个GameObject接受多个光照会为每一个per-pixel light产生多余的模型提交和绘制,从而附加了多个Pass导致无法合批,如下图:

可以接收多个光源的shader,在受到多个光源是无法合批

       总结:同时使用的Shader一定要是单Pass的。同时因为单Pass的限定,对于延迟渲染来说,由于将光照分离到单独的Pass去处理而导致受光的对象完全没有办法进行动态合批的操作,所以会直接屏蔽掉Dynamic Batching。

3、GPU Instanceing

     

适用前提:
兼容的平台及API

相同的Mesh与Material

支持不同的材质球属性块(MaterialPropertyBlock),用于解决动态修改材质的某些属性后无法合批的问题(因为动态改了相当于不同材质了)

不支持SkinnedMeshRenderer

Shader支持GPU Instancing

缩放为负值的情况下,会不参与加速。
受限于常量缓冲区在不同设备上的大小的上限,移动端支持的个数可能较低。
只支持一盏实时光,要在多个光源的情况下使用实例化,我们别无选择,只能切换到延迟渲染路径。为了能够让这套机制运作起来,请将所需的编译器指令添加到我们着色器的延迟渲染通道中。

效果:
  • 批渲染Mesh相同的那些物体,以降低DrawCall数
  • 这些物体可以有不同的参数,比如颜色与缩放,不同颜色要用(MaterialPropertyBlock)实现。

       使用 GPU Instanceing可使用少量绘制调用一次绘制(或渲染)同一网格的多个副本。它对于绘制诸如建筑物、树木和草地之类的在场景中重复出现的对象非常有用

  • GPU Instanceing在每次绘制调用时仅渲染相同的网格,但每个实例可以具有不同的参数(例如,颜色或比例)以增加变化并减少外观上的重复。
  • GPU Instanceing可以降低每个场景使用的绘制调用数量。可以显著提高项目的渲染性能。

         GPU Instanceing同样有一些使用限制条件:

  • Unity 自动选取要实例化的网格渲染器组件和 Graphics.DrawMesh调用。请注意,不支持 SkinnedMeshRenderer
  • Unity 仅在单个GPU实例化绘制调用中批量处理那些共享相同网格和相同材质的游戏对象。使用少量网格和材质可以提高实例化效率。要创建变体,请修改着色器脚本为每个实例添加数据

       参考文献:GPU实例化GPU 实例化 - Unity 手册GPU实例化

上面是官方文档对于GPU Instanceing的一些描述,可以看出与其他两种合批手段不同的是,除了材质相同之外,其主要是对于使用同一网格的物体有效,所以正如名字的Instanceing那样,是通过GPU直接对于某一物体进行实例化来降低CPU对场景物体的数据命令准备所产生的性能消耗的技术手段。 

原理:

简单地说就是一次对具有相同网格物体的多个对象发出一次绘图调用。CPU收集所有每个对象的变换和材质属性,并将它们放入数组中,然后发送给GPU。然后,GPU遍历所有条目,并按提供顺序对其进行渲染。

如何使用GUPInstancing:

   

//熊猫悟道
Shader "XiongMaoWuDao/Gpu_Instancing"
{Properties{_BaseColor("Color", Color) = (1.0, 1.0, 1.0, 1.0)}SubShader {Pass {HLSLPROGRAM// GUIInstancing  调用// 一次对具有相同网格物体的多个对象发出一次绘图调用。// CPU收集所有每个对象的变换和材质属性,并将它们放入数组中,然后发送给GPU(SetPassCall)。// 最后,GPU遍历所有条目,并按提供顺序对其进行渲染。#pragma multi_compile_instancing#pragma vertex vert#pragma fragment frag#include "UnlitPass.hlsl"					// 里面定义了顶点着色器以及片元着色器ENDHLSL}}
}// --------------以下是UnlitPass.hlsl里的代码-----------------// 为了支持GUIInstancing,这里CBUFFER_START改成用UNITY_INSTANCING_BUFFER_START宏UNITY_INSTANCING_BUFFER_START(UnityPerMaterial)UNITY_DEFINE_INSTANCED_PROP(float4, _BaseColor)								// 把所有实例的_BaseColor放入内存缓冲区UNITY_INSTANCING_BUFFER_END(UnityPerMaterial)// 顶点着色器输入
struct Attributes{float3 positionOS : POSITION;UNITY_VERTEX_i_INSTANCE_ID												// 启用GUIInstancing的时候,用此宏,可以让顶点传入实例化id
};// 顶点着色器输出
struct Varyings {float4 positionCS : SV_POSITION;UNITY_VERTEX_i_INSTANCE_ID												// 启用GUIInstancing的时候,用此宏,让顶点着色器输出实例化id
};Varyings vert(Attributes i){Varyings o;UNITY_SETUP_INSTANCE_ID(i);												// 从i中提取对象索引,并将其存储在其他GUIInstancing相关宏所依赖的全局静态变量中UNITY_TRANSFER_INSTANCE_ID(i, o);									// 把i中的实例化id转换到片元着色器中用的实例化idfloat3 positionWS = TransformObjectToWorld(i.positionOS);o.positionCS = TransformWorldToHClip(positionWS);return o;
}float4 frag(Varyings i) : SV_TARGET{UNITY_SETUP_INSTANCE_ID(i);												// 从i中提取对象索引,并将其存储在其他GUIInstancing相关宏所依赖的全局静态变量中return UNITY_ACCESS_INSTANCED_PROP(UnityPerMaterial, _BaseColor);			// 根据实例id从_BaseColor数组中取出对应的_BaseColor
}

当需要创建海量mesh的时候,一般不要用实例化游戏物体的方式,这样会比较消耗性能,推荐使用Graphics.DrawMeshInstanced来创建。

   例如  :

using System.Collections;
using System.Collections.Generic;
using UnityEngine;// 动态生成大量球体mesh,用来测试GPUInstancing
public class MeshBall : MonoBehaviour
{static int baseColorId = Shader.PropertyToID("_BaseColor");[SerializeField]Mesh mesh = default;         // 手动拖入mesh[SerializeField]Material material = default;  // 手动拖入支持GPUInstancing的材质球Matrix4x4[] matrices = new Matrix4x4[500];Vector4[] baseColors = new Vector4[500];MaterialPropertyBlock block;private void Awake(){for (int i = 0; i < matrices.Length; i++){matrices[i] = Matrix4x4.TRS(Random.insideUnitSphere * 10f, Quaternion.identity, Vector3.one);baseColors[i] = new Vector4(Random.value, Random.value, Random.value, 1f);}}private void Update(){if(block == null){block = new MaterialPropertyBlock();block.SetVectorArray(baseColorId, baseColors);}Graphics.DrawMeshInstanced(mesh, 0, material, matrices, 500, block);}
}

注意: Graphics.DrawMeshInstanced()这方法还有两问题

1.一次最多画1023个元素,如果超出就会报错,所以需要将草进行分类管理。

2.它不提供裁切的功能,也就是说摄像机看不到的地方,这些草是不会被剔除掉的,依然会被渲染。

解决这个问题,为了避免运行时暴力的for循环来判断是否在视野内,我采取的方法是预先将场景分成20X20若干个格子(可根据游戏的可视范围而定)根据玩家的位置,始终只渲染周围9个格子内的草元素,这样将大幅度减少运行时for循环的次数。

如果每个草的顶点色是不一样的怎么办呢?可以用MaterialPropertyBlock来让同一个材质求有不同的属性。

4、SRP Batcher

适用前提:
        需要是同一个shader变体,可以是不同的材质球,项目需要使用自定义渲染管线,Shader代码必须兼容SRP Batcher。

        但是不支持用材质球属性块(MaterialPropertyBlock)

        渲染的物体必须是一个mesh或者skinned mesh。不能是粒子。

效果:

        可以有效降低SetPassCall(设置渲染状态)的数目,用于CPU性能优化。

开启SRP Batch: 要使用 SRP Batcher,项目必须使用可编程渲染管线。可编程渲染管线可以是:

  • 通用渲染管线 (URP)
  • 高清渲染管线 (HDRP)
  • 自定义 SRP

由于后两种方式不常用,所以本文章会基于URP模板来介绍,而关于URP的具体细节,可以查看该文章:Unity 升级项目到Urp(通用渲染管线)以及画面后处理

当我们在项目中使用URP模板后,就可以在资源目录中找到当前项目的URP配置文件,在其中可以看到SRP Batcher的控制选项:

同时当项目在URP模板下时Dynamic Batching的开关控制选项也被迁移到了配置文件,但是相比于默认渲染管线该技术默认是被关闭的,因为其相对于SRP Batcher来说并没有优势

   参考文献:可编程渲染管线 SRP Batcher - Unity 手册

SRP Batcher原理:

Unity中,可以在一帧内的任何时间修改任何材质的属性。但是,这种做法有一些缺点。例如,DrawCall 使用新材质时,要执行许多作业。因此,场景中的材质越多,Unity 必须用于设置GPU 数据的 CPU也越多。解决此问题的传统方法是减少 DrawCall的数量以优化CPU 渲染成本,因为 Unity 在发出 DrawCall之前必须进行很多设置。实际的 CPU 成本便来自该设置,而不是来自 GPU DrawCall本身(DrawCall 只是 Unity需要推送到 GPU 命令缓冲区的少量字节)

正如Set Pass Call的描述那样,游戏在渲染阶段CPU的性能消耗主要在与材质切换阶段的一些作业,而SPR Batcher通过在GPU的数据缓冲区的持久化存储来换取CPU的新材质的准备时间,从而降低CPU的数据准备压力

SRP Batcher 通过批处理一系列 BindDraw GPU 命令来减少 DrawCall之间的 GPU 设置,具体过程如图所示:

     

            为了获得最大渲染性能,这些批次必须尽可能大。为了实现这一点,可以使用尽可能多具有相同着色器的不同材质,但是必须使用尽可能少的着色器变体

在内渲染循环中,当 Unity 检测到新材质时,CPU 会收集所有属性并在 GPU 内存中设置不同的常量缓冲区。GPU缓冲区的数量取决于着色器如何声明其 CBUFFER 。

为了在场景使用很多不同材质但很少使用着色器变体的一般情况下加快速度,SRP 在原生集成了范例(例如GPU 数据持久性)。

  SRP Batcher是一个低级渲染循环,使材质数据持久保留在 GPU 内存中。如果材质内容不变,SRP Batcher 不需要设置缓冲区并将缓冲区上传到 GPU。实际上,SRP Batcher 会使用专用的代码路径来快速更新大型 GPU 缓冲区中的 Unity 引擎属性,如下所示:

    

这是 SRP Batcher 渲染工作流程。SRP Batcher 使用专用的代码路径来快速更新大型 GPU 缓冲区中的 Unity 引擎属性。在此处,CPU仅处理上图中标记为 Per Object large buffer的 Unity 引擎属性。所有材质在 GPU 内存中都有持久的 CBUFFER,可供随时使用。这样会加快渲染速度,原因是: 现在,所有材质内容都持久保留在 GPU 内存中。 专用代码针对所有每对象属性,管理着一个大型的每对象GPU CBUFFER 。

优化原理:

        简单的说,就是把同一种shader对应的材质球的材质、颜色通通放到一个缓冲区中,不用每帧设置给GPU,每帧仅仅设置坐标、缩放、转换矩阵等变量给GPU。

SRP Batcher 限制条件:

为了使 SRP Batcher代码路径能够渲染对象:

  • 渲染的对象必须是网格或蒙皮网格。该对象不能是粒子。
  • 着色器必须与 SRP Batcher 兼容。HDRP 和 URP 中的所有光照和无光照着色器均符合此要求(这些着色器的“粒子”版本除外)。 为了使着色器与 SRP Batcher 兼容:
  • 必须在一个名为UnityPerDraw的 CBUFFER 中声明所有内置引擎属性。例如unity_ObjectToWorld 或 unity_SHAr
  • 必须在一个名为 UnityPerMaterial的 CBUFFER 中声明所有材质属性
如何让Shader支持SRPBatcher:
   1、必须声明所有内建引擎properties 在一个名为"UnityPerDraw"的CBUFFER里。

     

// 如果需要支持SRP合批,内置引擎属性必须在“UnityPerDraw”的 CBUFFER 中声明
CBUFFER_START(UnityPerDraw)
float4x4 unity_ObjectToWorld;			// 模型空间->世界空间,转换矩阵(uniform 值。它由GPU每次绘制时设置,对于该绘制期间所有顶点和片段函数的调用都将保持不变)
float4x4 unity_WorldToObject;			// 世界空间->模型空间
float4 unity_LODFade;
real4 unity_WorldTransformParams;		// 包含一些我们不再需要的转换信息,real4向量,它本身不是有效的类型,而是取决于目标平台的float4或half4的别名。(需要引入unityURP库里的"Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"才能使用real4)
CBUFFER_END

        注意:URP内置的UnityInput.hlsl里自带更全面的代码。也就是说,如果你的代码有引用或间接引用UnityInput.hlsl,那就不用做这一步了。

 2、必须声明所有材质properties在一个名为"UnityPerMaterial"的CBUFFER里。
// 使用核心RP库中的CBUFFER_START宏定义,因为有些平台是不支持常量缓冲区的。这里不能直接用cbuffer UnityPerMaterial{ float4 _BaseColor };
// Properties大括号里声明的所有变量如果需要支持合批,都需要在UnityPerMaterial的CBUFFER中声明所有材质属性
// 在GPU给变量设置了缓冲区,则不需要每一帧从CPU传递数据到GPU,仅仅在变动时候才需要传递,能够有效降低set pass call
CBUFFER_START(UnityPerMaterial)
float4 _BaseColor;															// 将_BaseColor放入特定的常量内存缓冲区
CBUFFER_END

若需要配合GPUInstancing则需要改写为

UNITY_INSTANCING_BUFFER_START(UnityPerMaterial)UNITY_DEFINE_INSTANCED_PROP(float4, _BaseColor)								// 把所有实例的_BaseColor以数组的形式声明并放入内存缓冲区
UNITY_INSTANCING_BUFFER_END(UnityPerMaterial)

 

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

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

相关文章

ICT测试原理

目录&#xff1a; 一、什么是ICT 二、ICT在哪使用 三、ICT如何测试 1、隔离(Guarding)原理 2、电容器测试原理 3、电感器测试原理 4、普通二极管测试方法(MODE D) 5、晶体管的测量原理 (三端点)(MODE TR) 6、短/开路的测试原理 1&#xff09;学习短路表 2&#xff…

基于chrome插件的企业应用

一、chrome插件技术介绍 1、chrome插件组件介绍 名称 职责 访问权限 DOM访问情况 popup 弹窗页面。即打开形式是通过点击在浏览器右上方的icon&#xff0c;一个弹窗的形式。 注: 展示维度 browser_action:所有页面 page_action:指定页面 可访问绝大部分api 不可以 bac…

【数据结构】排序算法——Lessen1

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

【动态专修】2024年五菱维修手册和电路图资料更新

经过整理&#xff0c;2017-2024年五菱汽车全系列已经更新至汽修帮手资料库内&#xff0c;覆盖市面上99%车型&#xff0c;包括维修手册、电路图、新车特征、车身钣金维修数据、全车拆装、扭力、发动机大修、发动机正时、保养、电路图、针脚定义、模块传感器、保险丝盒图解对照表…

人、智能、机器人……

在遥远的未来之城&#xff0c;智能时代如同晨曦般照亮了每一个角落&#xff0c;万物互联&#xff0c;机器智能与人类智慧交织成一幅前所未有的图景。这座城市&#xff0c;既是科技的盛宴&#xff0c;也是人性与情感深刻反思的舞台。 寓言&#xff1a;《智光与心影》 在智能之…

Python自动化DevOps任务入门

目录 Python自动化DevOps任务入门 一、环境和工具配置 1. 系统环境与Python版本 2. 虚拟环境搭建 3. 必要的库安装 二、自动化部署 1. 使用Fabric进行流式部署 2. 使用Ansible编写部署剧本 三、持续集成和测试 1. 配置CI/CD工具 选择工具 配置工具 构建和测试自动…

【SLAM】最最最简单的直线拟合情形下的多种求解方法

本文我们讨论一个最最最简单情况下的拟合的情形&#xff0c;并尝试使用不同的方法来进行求解。 假如有一组数 x 1 , x 2 , x 3 , . . . , x n x_1,x_2,x_3,...,x_n x1​,x2​,x3​,...,xn​&#xff0c;对应的值为 y 1 , y 2 , y 3 , . . . , y n y_1,y_2,y_3,...,y_n y1​,y2…

10.11和10.8那个大(各种ai的回答)

问题&#xff1a;10.11和10.8两个数哪个大 腾讯混元 ✔️ chatGPT ❎ 通义千问 ❎ 文心一言 ✔️ 智谱清言 ❎ 讯飞星火 ✔️ C知道 ❎ 豆包 ✔️

TCP粘包问题详解和解决方案【C语言】

1.什么是TCP粘包 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输协议&#xff0c;它保证了数据的可靠性和顺序性。然而&#xff0c;由于TCP是基于字节流而不是消息的&#xff0c;因此在传输过…

【接口自动化_08课_Pytest+Yaml+Allure框架】

上节课一些内容 的补充 1、openxl这个方法&#xff0c;第一个元素是从1开始的&#xff0c;不是从0开始 回写的列在程序里写的是11&#xff0c;是因为是固定值 一、1. Yaml入门及应用 1、什么是yaml YAML&#xff08;/ˈjməl/&#xff0c;尾音类似camel骆驼&#xff09;是一…

Finding columns with a useful data type 找到合适的数据列的类型

Finding columns with a useful data type 在确定了原始查询的数据列数之后&#xff0c;接下来就是要确定合适的数据列的数据类型。可以用 SELECT a 的方式判断对应的数据列方式&#xff0c;有时候可以通过错误信息判断数据列的类型。如果服务器的响应没有报错&#xff0c;而…

Docker启动PostgreSql并设置时间与主机同步

在 Docker 中启动 PostgreSql 时&#xff0c;需要配置容器的时间与主机同步。可以通过在 Dockerfile 或者 Docker Compose 文件中设置容器的时区&#xff0c;或者使用宿主机的时间来同步容器的时间。这样可以确保容器中的 PostgreSql 与主机的时间保持一致&#xff0c;避免在使…

启动流程和切换流程

启动流程 #mermaid-svg-iUWGw8xl1SyAmoo9 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-iUWGw8xl1SyAmoo9 .error-icon{fill:#552222;}#mermaid-svg-iUWGw8xl1SyAmoo9 .error-text{fill:#552222;stroke:#552222;}#…

C语言·分支和循环语句(超详细系列·全面总结)

前言&#xff1a;Hello大家好&#x1f618;&#xff0c;我是心跳sy&#xff0c;为了更好地形成一个学习c语言的体系&#xff0c;最近将会更新关于c语言语法基础的知识&#xff0c;今天更新一下分支循环语句的知识点&#xff0c;我们一起来看看吧~ 目录 一、什么是语句&#xf…

linux配置podman阿里云容器镜像加速器

1.下载podman yum install -y podman systemctl status podman systemctl start podman 2.获取阿里云个人容器镜像加速器地址 访问阿里云官网&#xff1a;首先&#xff0c;您需要访问阿里云&#xff08;Alibaba Cloud&#xff09;的官方网站。阿里云官网的URL是&#xff1a;…

OS:处理机进程调度

1.BackGround&#xff1a;为什么要进行进程调度&#xff1f; 在多进程环境下&#xff0c;内存中存在着多个进程&#xff0c;其数目往往多于处理机核心数目。这就要求系统可以按照某种算法&#xff0c;动态的将处理机CPU资源分配给处于就绪状态的进程。调度算法的实质其实是一种…

对于品牌方来说,小红书探店应该怎么做?

小红书是中国最大的生活分享社交平台之一&#xff0c;它现在不仅仅是一个购物推荐平台&#xff0c;也是一个探店的好去处。 用户在网络上看到一家心仪的店铺&#xff0c;却又无法亲身到访&#xff0c;对店铺的产品存疑&#xff0c;这时候就会在小红书搜索具体的相关店铺信息。 …

【代码随想录】【算法训练营】【第58天 4】 [卡码104]建造最大岛屿

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 卡码网。 day 58&#xff0c;周四&#xff0c;ding~ 题目详情 [卡码104] 建造最大岛屿 题目描述 卡码104 建造最大岛屿 LeetCode类似题目827 最大人工岛 解题思路 前提&#xff1a; 思路&#xff1a; 重点…

【LeetCode】从前序与中序遍历序列构造二叉树

目录 一、题目二、解法完整代码 一、题目 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9…

在西藏上大学是一种什么体验?如何解决语言问题?

在西藏地区上大学是一种独特而难忘的经历&#xff0c;它不仅提供了接触壮丽自然风光和深入了解藏族文化的机会&#xff0c;也带来了适应高原气候和生活方式的挑战。学生将在这里体验到丰富的教育资源和学术研究素材&#xff0c;同时在生活和人际交往中培养适应能力和独立性。这…