news 2026/9/10 13:23:08

用Python复刻我的世界小游戏:体素引擎与区块存储实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用Python复刻我的世界小游戏:体素引擎与区块存储实战

简介:这是一套基于Python和Pygame库实现的‘我的世界’风格二维沙盒小游戏源码,面向已经掌握Python基础语法、希望真正进入游戏开发领域的初学者。项目借助窗口创建、事件监听、方块绘制、碰撞检测与帧速率控制等机制,完整展示像素化沙盒游戏的核心交互流程;其中还涉及面向对象建模、简单音效处理与数据序列化思路,非常适合作为从语法学习过渡到项目实战的桥接案例。压缩包体积仅有15KB,共4个文件,分别对应主程序main.py、说明文档README.md、游戏纹理texture.png以及开源许可证LICENSE,文件数量精炼但代码组织清晰,方便逐行阅读与上机调试。当前已有7083人学习或下载,热度侧面反映了该资源的实用性。跟随源码梳理,读者既能理解Pygame初始化、主循环、事件响应、碰撞判定和动画刷新等常见游戏开发环节,也能借鉴其简洁的工程结构,快速搭建自己的小型游戏原型,为后续扩展存档、音效与更多玩法打下扎实基础。

1. 用 Python 复刻“我的世界”小游戏:先把体素引擎当成数据问题

搜索“python我的世界小游戏源代码”,大多数人想拿到的是一个能跑起来、能走能挖能放方块的方块世界,而不是一个完整的 MC 克隆。这个标题真正值钱的地方在于:复刻《我的世界》最难的不是渲染,而是把体素世界组织成结构化数据——方块怎么存、区块怎么切、视线里的目标方块怎么选中。这几个问题恰好又都是 Python 里最值得练的坐标与数据结构题。

所以这篇按一条最容易验收的路子来写:Python 3 环境加 ursina 引擎,用几百行代码搭出第一人称体素小游戏的骨架,同时把存储、拾取、存档三个最容易写崩的点埋进去。纯色贴图,不依赖外部美术资源,笔记本上就能跑。新手可以照着一步步跑通;写过几年 Python 的读者也可以在这个骨架上对比一下“字典存方块”“区块 bytearray”“延迟落盘”这些方案的边界。

2. 区块与方块类型:Python“我的世界”小游戏源代码的世界存储层

2.1 用字典还是数组存方块:先定 block_type 表

所有体素引擎的第一步都是回答同一个问题:给定一个整数坐标 (x, y, z),这个位置是什么。最常见的答案是维护一张(x, y, z) -> int的映射,整数在这里不是 RGB 颜色,而是方块类型编号:0 是空气,1 是草方块,2 是泥土,3 是石头。

这段代码就是把这种映射落成最小实现:

# 方块类型表:编号 -> 名称、颜色、是否为实体 BLOCK_TYPES = { 0: {"name": "air", "color": None, "solid": False}, 1: {"name": "grass", "color": (0.3, 0.8, 0.2), "solid": True}, 2: {"name": "dirt", "color": (0.5, 0.3, 0.1), "solid": True}, 3: {"name": "stone", "color": (0.5, 0.5, 0.5), "solid": True}, } class World: def __init__(self, chunk_size=16, world_height=64): self.blocks = {} # (x, y, z) -> block_id self.chunk_size = chunk_size self.world_height = world_height def set_block(self, x, y, z, block_id): if block_id == 0: # 挖掉方块 = 从字典中删除,而不是写入 0 self.blocks.pop((x, y, z), None) else: self.blocks[(x, y, z)] = block_id def get_block(self, x, y, z): # 查不到就是空气 return self.blocks.get((x, y, z), 0)

逻辑说明:set_block里对空气单独处理,是因为方块世界天然稀疏,地面以上几百格都是空气。如果挖掉一个方块还继续把它留在字典里占位,一次探索下来字典里会堆积大量无意义的空键。用pop删除,才是真正的稀疏存储。

参数说明:world_height是这个世界允许的最高 y 值,后面做区块数组和存档边界检查都会用到;chunk_size是区块边长,先取 16。这个值是体素游戏里最常见的区块尺寸,下一节说明为什么不是 8 也不是 32。

2.2 区块 16 × 16 这个数字从哪里来

“区块”是《我的世界》世界观里的经典概念:把世界按水平方向切成若干方块组,每个组作为一个独立的加载、保存和裁剪单位。这个标题下的 Python 小游戏也继承了这个设计。区块尺寸的常见选择如下:

区块边长单区块方块数(按 64 层高)对渲染裁剪的帮助实际体验
84096太碎片化,走几步就要重新检查外围区块加载频繁,存档文件零碎
16163845×5 的区块阵列就能覆盖常见视野体素小游戏最常用的折中值
3265536边缘过大,可见性裁剪不精细适合做“区域”而不是最小单位

确定边长后,就要处理世界坐标到区块坐标的换算。这个环节在 Python 里有一个特别容易被忽视的坑:负数的//%是向下取整,而不是向零取整。

def block_key(x, y, z): # 世界坐标转区块坐标 + 区块内局部坐标 cx, cz = x // 16, z // 16 lx, lz = x % 16, z % 16 return cx, cz, lx, y, lz # 验证:世界坐标 -1 会落到区块 -1 的局部坐标 15 assert block_key(-1, 5, -1) == (-1, -1, 15, 5, 15) # 再由区块坐标算回世界坐标 wx = -1 * 16 + 15 # 结果是 -1

逻辑说明:x // 16x % 16是配套的一对操作,cx * 16 + lx永远还原成原坐标。如果用int(x / 16)代替//,-1 会被截断成 0,局部坐标却是 15,整个世界的 x 轴左侧就会错位一格。

参数说明:block_key返回的cy没有参与计算,因为小游戏世界默认永不改变 y 方向上的区块边界,整个世界高度就固定为world_height。如果你要做地下世界或天空岛,再把 y 也纳入区块坐标,原理完全相同。

2.3 区块内用 bytearray:比字典更“抠”的实现

字典解决的是“整个世界稀疏存”的问题,但如果一个区块内部已经被填满,还用字典逐格存储,内存开销就明显了。Python 的 int 是对象,一个格子放进字典至少占用几十字节;而 16×16×64 的区块总共 16384 个格子,完全可以退化成连续数组。

class Chunk: def __init__(self, cx, cz, height=64): self.cx, self.cz = cx, cz self.height = height # 一维 bytearray:每个字节存一个方块 id self.blocks = bytearray(16 * 16 * height) def index(self, x, y, z): # 把 x 放最低位,y 放最高位 return x + z * 16 + y * 256 def get(self, x, y, z): return self.blocks[self.index(x, y, z)] def set(self, x, y, z, block_id): self.blocks[self.index(x, y, z)] = block_id

逻辑说明:bytearray每个元素是 0 到 255 的无符号整数,一个格子的存储代价是 1 字节。index的展开顺序是x + z * 16 + y * 16 * 16,也就是内存里 x 方向连续排列。生成地形时如果按 x 内层循环写,内存访问顺序也就连续了。

参数说明:单区块 16384 字节,5×5 的区块阵列才 400 KB 左右,这就是为什么 bytearray 方案能让“我的世界小游戏”直接在普通笔记本上跑起来。但这套方案只适合方块 id 不超过 255 的场景,如果需要 256 种以上方块,就要换成array('H')或 numpy 的uint16数组。

2.4 世界生成从“高度图”开始,而不是随机撒方块

初学者写体素世界很容易直接在三维坐标里 random,结果是满地斑点,不像地形。常见做法是先生成一张二维高度图,再根据高度值逐列填充方块。下面的代码就是在 16×16 区块里用多个正弦波叠加模拟缓慢起伏的地形:

from math import sin def generate_chunk(cx, cz, chunk_size=16): chunk = Chunk(cx, cz) for lx in range(chunk_size): for lz in range(chunk_size): wx = cx * chunk_size + lx wz = cz * chunk_size + lz # 多层正弦叠加:大周期控制山丘,小周期控制起伏 height = int(6 + 3 * sin(wx * 0.08) + 2 * sin(wz * 0.08)) height = max(1, height) for y in range(height): block_id = 1 if y == height - 1 else 2 # 顶部草方块,下面泥土 chunk.set(lx, y, lz, block_id) return chunk

逻辑说明:height是这一列地表方块的 y 值。草地只放在最高一层,下面全是泥土,这是《我的世界》地表结构的简化版。正弦波的系数 0.08 控制地形起伏频率,越大山丘越密集。

参数说明:最外层int(...)之后要接max(1, height),防止正弦值叠加后出现 0 层的地形空洞。如果你觉得地形太单调,再加不同频率和振幅的正弦项;如果觉得太规则,把其中一项换成随机数种子,就能得到更自然的噪声地形。

3. 用 ursina 搭第一人称“我的世界”小游戏:从最小原型开始

3.1 为什么选 ursina 而不是 pygame

想做 3D 第一人称体素小游戏,行内最常见的可靠方案是 ursina。它构建在 Panda3D 之上,自带第一人称控制器、实体射线检测和立方体模型,正好覆盖“我的世界”类小游戏的三件套:移动、挖掘、放置。如果坚持用 pygame 从零写投影和碰撞,工作量会落在矩阵变换上,而不是体素逻辑本身。

方案第一人称控制器方块拾取立方体渲染适合场景
pygame 自写 3D自己写投影和碰撞自己写射线求交自己写图元2D 或等距视角的简化版
ursina内置 FirstPersonController内置 raycast内置 cube 模型3D 第一人称体素小游戏
Panda3D 裸写自己拼装自己拼装内置追求底层控制的中大型项目

3.2 最小项目初始化:venv 加 ursina

先把环境准备好。下面这段命令在不同系统上只有激活语句不同:

python -m venv .venv # Windows: .venv\Scripts\activate # macOS / Linux: source .venv/bin/activate pip install ursina

参数说明:用 venv 而不是直接往全局环境里装,是为了不污染系统 Python。ursina 依赖 panda3d,安装包体积不小,建议网络条件一般时用国内镜像源:pip install ursina -i https://pypi.tuna.tsinghua.edu.cn/simple

3.3 第一人称控制器的 5 个必调参数

FirstPersonController是 ursina 提供的现成控制器,但默认参数手感偏“快”,复刻方块世界时需要调整。最影响手感的是下面这张表里的参数:

参数默认值我的建议值作用说明
speed1410地面移动速度,原版 MC 步行约 4.3 米/秒,小游戏里可适当加快
jump_height11.4跳跃高度,低于 1 会跳不上 1 格高的台阶
jump_duration0.40.3跳跃滞空时间,值越大跳得越“飘”
gravity11.5重力系数,越大下落越快
mouse_sensitivityVec2(40, 40)Vec2(25, 25)鼠标灵敏度,默认太快,容易转晕

最小可玩代码看起来像这样:

from ursina import * app = Ursina() player = FirstPersonController( position=(0, 10, 0), speed=10, jump_height=1.4, jump_duration=0.3, gravity=1.5, mouse_sensitivity=Vec2(25, 25), ) app.run()

逻辑说明:position=(0, 10, 0)是把玩家生成在高度 10,避免出生点卡进地面。Ursina()必须先创建,再实例化任何实体。app.run()进入主循环,之后所有键盘鼠标事件都由 ursina 分发。

参数说明:jump_height与“能否跳上一格方块”直接相关。一块方块的边长是 1,玩家脚底要越过 top 面至少 1 个游戏单位,所以 1 是极限值,留出 0.4 的余量更稳妥。

3.4 把方块画出来:Button 既是模型又是触发器

在 ursina 里,可点击的方块通常用Button而不是普通Entity,因为Button默认带collider='box'并且能响应鼠标点击。这意味着方块既能被玩家踩在脚下,又能被鼠标选中,省去手写碰撞体。

class Block(Button): def __init__(self, position=(0, 0, 0), block_type=1): r, g, b = BLOCK_TYPES[block_type]["color"] super().__init__( parent=scene, model="cube", texture="white_cube", # 纯白贴图,靠 color 染色 color=color.rgb(r * 255, g * 255, b * 255), position=position, collider="box", block_type=block_type, ) def build_world_from_chunks(world): for (cx, cz), chunk in world.chunks.items(): origin_x = cx * world.chunk_size origin_z = cz * world.chunk_size for x in range(16): for y in range(chunk.height): for z in range(16): block_id = chunk.get(x, y, z) if block_id != 0: Block(position=(origin_x + x, y, origin_z + z), block_type=block_id)

逻辑说明:texture="white_cube"是 ursina 内置的白色立方体贴图,配合color染色,一个方块类型只需要改颜色值,不用准备多张贴图。三层循环会遍历区块里的所有格子,空气直接跳过,不生成实体。

参数说明:这段代码最耗时的部分是循环本身。一个区块最多 16384 个格子,5×5 区块就是 409600 次循环。如果初始化明显卡顿,最简单的优化是只画裸露在外层的方块,也就是那些至少有一个相邻面是空气的方块。我在小项目里常用的做法是:x 或 z 等于 0 或 15,以及 y 等于 height-1 的格子才生成Block,其余默认玩家看不到。

3.5 锚点与坐标系:脚陷进地面半格的问题

实体默认的锚点是中心,而方块塌落下来时玩家站在“中心高度 + 半格”的位置,视觉上脚会陷进去。解决办法是在Block里加origin_y=0.5,把锚点从中心移到方块底部:

class Block(Button): def __init__(self, position=(0, 0, 0), block_type=1): ... super().__init__( ..., origin_y=0.5, # 锚点放在底部,玩家站在 y 整数位 )

逻辑说明:ursina 的 y 轴向上,方块的几何中心在y + 0.5。不设origin_y,玩家站在方块顶上时脚底会被碰撞体抬到y + 1,行走时每一步都像踩在空气上。origin_y=0.5之后,方块的碰撞底面和视觉底面重合在y处。

参数说明:如果你后续给方块加缩放动画,要注意origin_y是按模型原始尺寸计算的,缩放值会叠加在锚点上。想要“方块从地里长出来”的效果,把锚点放到底部再配合scale_y动画是最省事的做法。

4. 目标方块拾取:放方块和挖方块怎么选中视线里的那一格

4.1 用 raycast 做第一版拾取

放置和破坏的“瞄准”逻辑,本质是求一条视线射线与最近方块的交点。ursina 的raycast返回碰撞实体和碰撞点法线,这正是一个体素小游戏需要的全部信息:

def get_target_block(): hit_info = raycast( camera.world_position, camera.forward, distance=8, # 拾取距离,经典 FPS 数值 ignore=[player], # 别打到自己 ) return hit_info def input(key): if key == "left mouse down": hit = get_target_block() if hit.hit: pos = hit.entity.position world.set_block(int(pos.x), int(pos.y), int(pos.z), 0) destroy(hit.entity) # 从场景中移除实体 elif key == "right mouse down": hit = get_target_block() if hit.hit: # 放置位置 = 被击中方块 + 表面法线方向 px = int(hit.world_point.x + hit.normal.x * 0.1) py = int(hit.world_point.y + hit.normal.y * 0.1) pz = int(hit.world_point.z + hit.normal.z * 0.1) if world.get_block(px, py, pz) == 0: world.set_block(px, py, pz, 1) Block(position=(px, py, pz), block_type=1)

逻辑说明:破坏时直接取hit.entity.position,因为被击中的方块实体坐标就是它的格子坐标。放置时不能拿camera.forward加在方块坐标上,因为视线方向是连续向量,加出来大概率落在空中或方块内部;正确做法是取碰撞点加上“表面法线×极小偏移”,再进行整数化。hit.normal是碰撞面的朝向,乘 0.1 是为了让碰撞点从表面外部一点开始取整。

参数说明:distance=8是拾取距离,数值越大能挖到越远的方块。生存玩法想要“贴身挖掘”的手感,可以改成 3;想要测试世界生成,12 也不是不行。ignore=[player]不能少,否则从玩家内部打出的射线会先撞上玩家自己的碰撞体。

4.2 射线命中的三种常见实现

如果不想依赖 ursina 的高层 raycast,或者想要更精确地按“格子”拾取,可以自己实现体素射线步进。常见方案对比:

方案精度性能实现难度适合场景
ursina 自带 raycast基于实体包围盒快,只扫描场景实体小游戏首选
均匀步进采样有漏检风险O(距离/步长)理解原理、教学演示
DDA 网格步进精确到格O(穿过的格子数)追求手感与通用性

均匀步进采样是所有自写方案里最容易看懂的:

def raycast_voxel(origin, direction, max_distance=8.0): step_size = 0.05 # 步长越小越不容易漏,但开销越大 steps = int(max_distance / step_size) x, y, z = origin dx, dy, dz = direction for _ in range(steps): x += dx * step_size y += dy * step_size z += dz * step_size block_id = world.get_block(int(x), int(y), int(z)) if block_id != 0: return int(x), int(y), int(z) return None

逻辑说明:每一步把射线位置向前推进 0.05 个游戏单位,然后查询该位置所在的方块。因为方块边长是 1,理论上步长小于 0.5 就不会穿模,取 0.05 是图个省心。

参数说明:步长越小精度越高,但循环次数线性增加。max_distance=8时循环 160 次,性能完全可接受;如果把距离改成 100,就要考虑 DDA 或把步长增大到 0.1。均匀步进的另一个弱点是斜向射线在格子角落附近可能连续两个采样点跨越格子边界,这也就是表中“有漏检风险”的意思。

4.3 防止误操作:冷却时间与边界限制

“我的世界”小游戏里最常见的误操作是按住鼠标左键连挖,一瞬间把面前的好几个方块全拆了。因为主循环每帧都会调用input,鼠标按下的那一帧和按住不放的后续帧都会触发。

from ursina import time last_use_time = 0 def try_use_block(): global last_use_time if time.time() - last_use_time < 0.2: # 200ms 冷却 return last_use_time = time.time() # 上面的放置与破坏逻辑放这里

逻辑说明:time.time()是 ursina 自带的秒级计时器。每次操作后记录当前时间,下一次操作距离上次不足 0.2 秒就直接忽略。这个机制同时作用于挖掘和放置,避免误触。

参数说明:0.2 秒对应 5 次/秒的操作频率,比较接近手动点按的极限。想做“连锁挖矿”就把冷却缩短到 0.05 秒,想做“钝器手感”就调到 0.3 秒以上。冷却时间不要小于主循环的帧间隔,否则等于没设。

边界限制方面,我通常会在世界里记录一个水平半径radius,放置时把 x、z 限制在-radius * chunk_sizeradius * chunk_size之间。如果不加这一层限制,玩家可以走到未生成区块放一个孤立方块,存档时再一带一整套边界逻辑,很麻烦。

5. 让源代码更像成品:方块存档与区块预生成调度

5.1 存档选 JSON 还是 SQLite

做到能挖能放之后,下一步是退出程序再进来,世界还在。小体量项目里最常用的三种持久化方案各有边界:

存档方式回写速度数据结构友好度适合场景
JSON 全量 dump数据量大后保存卡顿高,json.dump一行搞定演示项目、单文件存档
按区块分文件只写脏区块,快中,要处理目录结构中等大小世界
SQLite 单库随机读写快中,需要建表想顺手练 sqlite3 的场景

JSON 全量 dump 是最容易跑通的做法,而且世界数据本身就是字典,序列化非常直观:

import json def save_world(world, path="world.json"): blocks = [] for (x, y, z), block_id in world.blocks.items(): blocks.append([x, y, z, block_id]) with open(path, "w", encoding="utf-8") as f: json.dump({"chunk_size": world.chunk_size, "world_height": world.world_height, "blocks": blocks}, f) def load_world(world, path="world.json"): with open(path, "r", encoding="utf-8") as f: data = json.load(f) world.chunk_size = data["chunk_size"] world.world_height = data["world_height"] world.blocks = {(x, y, z): block_id for x, y, z, block_id in data["blocks"]}

逻辑说明:字典的 key 是元组,元组不能直接作为 JSON key,所以先转成[x, y, z, block_id]的列表再存。读档时再用列表推导式还原成字典。chunk_sizeworld_height一起存是为了防止读档时用到不同的世界边界。

参数说明:JSON 方案在方块数达到几十万级时会明显变慢。如果你预计存档里方块超过 50 万,趁早换 sqlite3,表结构就用一列 rowid 加x, y, z, block_id四列,再给(x, y, z)建唯一索引即可。

5.2 按玩家坐标做区块预生成调度

“我的世界”小游戏碰到的最常见性能瓶颈不是方块太多,而是出生点一次性把所有区块全部生成。正规做法是以玩家目前所在区块为中心,只生成视距内的方块,离开视距就卸载。

def update(self): cx = int(player.x) // world.chunk_size cz = int(player.z) // world.chunk_size # 以玩家为中心,按视距预生成 for ox in range(-view_radius, view_radius + 1): for oz in range(-view_radius, view_radius + 1): key = (cx + ox, cz + oz) if key not in self.chunks: chunk = generate_chunk(cx + ox, cz + oz) self.chunks[key] = chunk # 只有新生成的区块需要渲染成实体 render_chunk_entities(chunk) # 超出视距的区块卸载并释放实体 for key in list(self.chunks.keys()): if abs(key[0] - cx) > view_radius or abs(key[1] - cz) > view_radius: unload_chunk(self.chunks.pop(key))

逻辑说明:update每个主循环帧都会被调用。第一段双层循环负责补上新增区块,第二段用list(...)快照遍历,是因为边遍历边pop会跳过元素。view_radius表示玩家四周保留几圈区块。

参数说明:view_radius=2时保留 5×5 共 25 个区块,约 40 万个格子,中等配置的笔记本可以流畅跑。调成 4 就是 81 个区块,实体数量会明显上升,此时必须配合“只生成裸露方块”的优化。

5.3 用脏区块计数控制落盘频率

存档最怕在游戏进行中频繁全量写盘。我一般会为每个区块维护一个修改计数,达到阈值才真正落盘:

chunk_dirty = {} def set_block_with_dirty(x, y, z, block_id): world.set_block(x, y, z, block_id) key = (x // world.chunk_size, z // world.chunk_size) chunk_dirty[key] = chunk_dirty.get(key, 0) + 1 if chunk_dirty[key] >= 64: save_chunk_to_json(key) chunk_dirty[key] = 0

逻辑说明:set_block被挖矿和放置两条逻辑共用,所以把脏计数放在这里最省事。阈值 64 意味着一个区块内累计 64 次方块变更就写一次盘。玩家退出时再做一次全量保存收尾。

参数说明:64 这个数字基于“每帧最多改几个方块”的经验值。如果想更稳,可以在app.step的末尾检测当前帧距上次写盘是否超过 3 秒,时间与次数两个条件用“或”的关系触发落盘。要注意的是,chunk_dirty计数只有在方块真正改变时才递增,连续点击同一个位置不会触发无意义的写盘,因为set_block里相同方块 id 的赋值不会更新字典。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 13:22:01

YOLOv5双目测距毕设实战:标定、视差与三维映射全链路解析

简介&#xff1a;本资源是一套完整的毕业设计级项目方案&#xff0c;面向计算机视觉方向的本科生与初学者&#xff0c;解决目标检测与三维空间距离测量的融合实践问题。项目基于YOLOv5实现高效目标识别&#xff0c;并结合双目摄像头标定与视差计算完成实时距离估计&#xff0c;…

作者头像 李华
网站建设 2026/9/10 13:21:56

OpenVoice即时语音克隆:10秒参考音频,让它用你的声音说话

OpenVoice即时语音克隆&#xff1a;10秒参考音频&#xff0c;让它用你的声音说话 【免费下载链接】OpenVoice Instant voice cloning by MIT and MyShell. Audio foundation model. 项目地址: https://gitcode.com/GitHub_Trending/op/OpenVoice OpenVoice 是 MIT 与 My…

作者头像 李华
网站建设 2026/9/10 13:18:36

数据库性能优化:程序操作优化策略与实践

1. 程序操作优化在数据库性能中的核心地位数据库性能优化从来都不是单一维度的技术活&#xff0c;而程序操作优化恰恰是最容易被忽视的关键环节。我见过太多团队在硬件配置和索引设计上投入大量精力&#xff0c;却对应用程序中的数据库操作代码放任自流。实际上&#xff0c;根据…

作者头像 李华
网站建设 2026/9/10 13:18:15

湖南家长必读:如何帮孩子规划单招升学

在湖南&#xff0c;越来越多家长已经认清升学现实&#xff1a;文化课成绩中等、偏薄弱的孩子&#xff0c;硬拼夏季高考&#xff0c;大概率无缘公办大专&#xff0c;最终要么高价就读民办院校&#xff0c;要么直接落榜无学可上。而高职单招作为湖南省教育厅、省教育考试院官方统…

作者头像 李华
网站建设 2026/9/10 13:17:37

CANN/GE流分配概要API

GetStreamAllocationSummary 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch…

作者头像 李华