揭秘Unity中C#协程滥用问题:如何避免帧率暴跌并提升游戏流畅度

【unity框架开发4】封装unity协程工具,避免 GC(垃圾回收) 在 Unity 中,使用 yield return null 、yield return new WaitForEndOfFrame()等会导致 GC(垃圾回收)开销。yield return null: 每次调用这个语句,Unity 会创建一个新的迭代器状态机。当你执行协程时,如果你在协程中使用 yield return null,它会生成一个新的迭代器,这样会产生额外的内存分配。 阅读详情

第一章:揭秘Unity中C#协程的本质与运行机制

在Unity引擎中,协程(Coroutine)是一种强大的异步编程工具,允许开发者以同步代码的形式编写延迟执行、分帧操作或时间驱动逻辑。其本质是基于C#的迭代器(Iterator)机制,通过 yield 语句控制程序执行流程的暂停与恢复。

协程的基本语法与执行流程

协程必须返回 IEnumerator 类型,并使用 yield return 指令定义暂停点。Unity的主线程会在每一帧检查协程的返回值,决定是否继续执行。

using UnityEngine;
using System.Collections;

public class CoroutineExample : MonoBehaviour
{
    // 启动协程
    void Start()
    {
        StartCoroutine(MyCoroutine());
    }

    // 定义协程
    IEnumerator MyCoroutine()
    {
        Debug.Log("协程开始");
        yield return new WaitForSeconds(2f); // 暂停2秒
        Debug.Log("2秒后执行");
        yield return null; // 等待下一帧
        Debug.Log("下一帧执行");
    }
}
上述代码中,StartCoroutine 注册协程,Unity内部通过迭代器的 MoveNext() 方法推进执行,直到迭代结束。

协程背后的迭代器状态机

C#编译器将包含 yield 的方法编译为一个状态机类,记录当前执行位置。每次调用 MoveNext() 时,状态机判断应继续执行还是暂停。
  • 协程并非多线程,运行在主线程上
  • 使用 StopCoroutine 可显式终止协程
  • 多个协程可并行执行,由Unity调度管理
yield 指令行为说明
yield return null等待一帧后继续
yield return new WaitForSeconds(1f)延迟1秒后继续
yield return StartCoroutine(another)嵌套执行另一个协程

第二章:深入理解协程的工作原理与性能代价

2.1 协程背后的迭代器与状态机解析

协程的本质是用户态的轻量级线程,其核心实现依赖于迭代器与状态机的结合。当协程被挂起或恢复时,实际上是通过状态机记录当前执行位置,并在下一次调度时从该点继续。
状态机驱动的协程切换
每个协程在编译后会被转换为一个状态机,状态值对应代码中的挂起点。例如,在 Go 中,编译器会将含有 await 或 yield 的函数拆解为带状态字段的结构体。

type StateMachine struct {
    state int
    ch    chan int
}
func (sm *StateMachine) Next() bool {
    switch sm.state {
    case 0:
        sm.state = 1
        return true
    case 1:
        return false
    }
}
上述代码模拟了协程状态跳转逻辑:每次调用 Next() 时根据当前 state 决定执行路径,实现暂停与恢复。
与迭代器的融合机制
协程可视为增强版迭代器,遵循 Iterator 模式。其 next() 方法不仅返回值,还携带控制流状态,使得异步操作能以同步形式表达。

2.2 StartCoroutine的开销与内存分配分析

在Unity中,StartCoroutine是协程启动的核心方法,但其背后存在不可忽视的性能代价。每次调用都会生成新的IEnumerator实例,导致堆内存分配,频繁调用可能引发GC压力。
协程的内存分配机制
Unity为每个协程创建引用对象以维护状态机,包括当前执行位置、局部变量和迭代器对象。这在频繁启停场景下尤为昂贵。
IEnumerator ExampleCoroutine() {
    yield return new WaitForSeconds(1f);
}
上述代码每次调用StartCoroutine(ExampleCoroutine())都会分配新对象。建议缓存IEnumerator引用以复用。
优化策略对比
方式内存分配适用场景
直接调用高一次性任务
缓存IEnumerator低频繁重复任务

2.3 协程泄漏的常见场景与检测方法

常见泄漏场景
协程泄漏通常发生在启动的协程未正常退出。典型场景包括:无限循环中缺少退出条件、通道操作阻塞导致协程挂起、以及未正确使用 context 控制生命周期。
  • 未关闭的接收通道导致协程永久阻塞
  • 使用 goroutine 执行回调但无超时机制
  • 在 select 中监听已失效通道
代码示例与分析
func leak() {
    ch := make(chan int)
    go func() {
        val := <-ch // 阻塞,无发送者
        fmt.Println(val)
    }()
    // ch 无发送者,协程无法退出
}
上述代码中,子协程等待从无发送者的通道接收数据,导致永久阻塞。主协程未关闭通道或提供默认退出路径,形成泄漏。
检测手段
可借助 Go 的 pprof 工具采集运行时协程堆栈:
工具用途
net/http/pprof实时查看协程数量
go tool pprof分析调用栈

2.4 yield指令的性能差异对比(yield return null vs WaitForSeconds)

在Unity协程中,yield return null与WaitForSeconds是常见的暂停方式,但性能表现有显著差异。
执行机制解析
  • yield return null:每帧结束时继续执行,不分配GC内存;
  • new WaitForSeconds(seconds):需实例化对象,产生GC压力。
IEnumerator ExampleCoroutine() {
    while (true) {
        // 高频调用推荐
        yield return null; 
    }
}
该代码适用于每帧更新逻辑,避免频繁内存分配。
性能对比数据
指令类型GC分配适用场景
yield return null无每帧执行
WaitForSeconds有定时延迟
对于高频或长期运行的协程,优先使用yield return null以提升性能。

2.5 多帧协程任务对GC压力的影响实践剖析

在高并发场景下,多帧协程任务频繁创建与销毁会导致堆内存快速膨胀,显著增加垃圾回收(GC)负担。尤其在每帧启动轻量协程处理异步逻辑时,短期对象激增易触发频繁的Minor GC。
协程频繁创建示例

for frame := range ticker {
    go func() {
        data := make([]byte, 1024)
        process(data)
    }()
}
上述代码每帧生成新协程并分配内存,导致大量临时对象驻留堆空间。尽管单次开销小,但累积效应会加剧GC扫描频率和停顿时间。
优化策略对比
  • 使用协程池复用执行单元,减少goroutine创建频次
  • 预分配缓存对象,避免重复内存申请
  • 通过sync.Pool管理临时对象生命周期
方案GC暂停(ms)堆峰值(MB)
原始方式18.7423
协程池+Pool6.3198

第三章:识别协程滥用的典型代码模式

3.1 频繁启动协程导致的帧率波动案例解析

在高并发场景下,频繁启动大量Go协程可能导致调度器负载激增,进而引发应用帧率波动。此类问题常见于实时渲染或游戏服务器中,协程创建速率远超GC回收能力。
典型问题代码

for {
    select {
    case data := <-ch:
        go func(d Data) {
            process(d) // 每次触发均启动新协程
        }(data)
    }
}
上述代码每次接收到数据即启动一个新协程,短时间内可能产生数千个协程,加剧Goroutine调度开销与内存占用。
优化策略
  • 使用协程池限制并发数量,复用已有协程
  • 引入缓冲通道控制任务提交速率
  • 通过sync.Pool减少对象分配压力
合理控制协程生命周期,可显著提升系统稳定性与响应性能。

3.2 嵌套协程引发的逻辑混乱与性能瓶颈

在复杂异步系统中,嵌套协程常因层级调用过深导致执行流难以追踪,进而引发资源竞争和状态不一致问题。
典型嵌套场景示例
go func() {
    go func() {
        result := fetchData()
        log.Println(result)
    }()
}()
上述代码在父协程中启动子协程处理数据请求。由于缺乏同步机制,子协程生命周期不可控,可能导致主流程退出后子协程仍在运行,造成 goroutine 泄漏。
性能影响分析
  • 调度开销随嵌套层数指数级增长
  • 共享变量访问冲突概率显著上升
  • 错误传播路径断裂,增加调试难度
合理使用 context 控制取消信号传递,可有效缓解深层嵌套带来的副作用。

3.3 不当使用WaitForSecondsFixed与跨场景协程残留问题

在Unity协程中,WaitForSecondsFixed常被误用于帧同步逻辑,但实际上它受Time.timeScale影响,导致在暂停或慢动作场景中产生不可预知的延迟。
常见误用场景
  • WaitForSecondsFixed并非固定物理帧等待,应使用WaitForFixedUpdate替代
  • 跨场景切换时未终止协程,导致引用丢失引发空指针异常
IEnumerator BadExample() {
    yield return new WaitForSecondsFixed(2f); // 错误:受Time.timeScale影响
    gameObject.transform.position = Vector3.zero;
}
上述代码在Time.timeScale=0时将无限阻塞。正确做法是结合WaitForFixedUpdate与生命周期管理。
协程生命周期管理
方法用途
StopCoroutine显式终止指定协程
OnDisable场景切换时自动调用,适合清理协程

第四章:高效替代方案与最佳实践策略

4.1 使用Update与状态标记优化简单延时逻辑

在处理需要延时执行的逻辑时,直接使用定时器可能导致资源浪费或状态不同步。通过引入状态标记与 Update 机制,可有效控制执行时机。
状态驱动的更新模式
利用布尔标记位判断是否满足执行条件,结合主循环中的 Update 方法轮询检测,避免频繁创建定时任务。

void Update() {
    if (shouldDelay && Time.time >= nextExecuteTime) {
        ExecuteAction();
        shouldDelay = false; // 状态标记重置
    }
}
上述代码中,shouldDelay 作为控制开关,nextExecuteTime 定义触发时刻。每次 Update 检查当前时间是否到达预期,确保操作在合适时机执行,同时减少不必要的性能开销。
  • 状态标记提升逻辑可控性
  • Update 轮询适合高频低延迟场景
  • 避免多协程或 Invoke 带来的内存压力

4.2 引入对象池管理协程生命周期减少开销

在高并发场景下,频繁创建和销毁协程会带来显著的内存分配与GC压力。通过引入对象池(sync.Pool)复用协程上下文对象,可有效降低资源开销。
对象池优化协程启动
使用 sync.Pool 缓存协程所需的上下文结构体,避免重复分配:
var contextPool = sync.Pool{
    New: func() interface{} {
        return &HandlerContext{}
    },
}

func spawnWorker(task Task) {
    ctx := contextPool.Get().(*HandlerContext)
    ctx.Task = task
    go func() {
        defer contextPool.Put(ctx) // 复用完成后归还
        process(ctx)
    }()
}
上述代码中,每次启动协程时从池中获取上下文实例,执行完毕后归还。减少了堆分配次数,减轻了GC负担。
性能对比
方案每秒处理量内存分配(MB)
直接新建12,00085.3
对象池复用27,50012.7

4.3 基于Job System与Burst编译的高性能替代思路

Unity 的 Job System 与 Burst 编译器组合为游戏性能优化提供了全新路径。通过将繁重的计算任务拆分为可并行执行的工作单元,显著提升 CPU 利用率。
数据同步机制
使用 IJobParallelFor 可安全地对大型数组进行并行处理,配合 NativeArray 实现托管与非托管内存的高效交互:

struct MoveJob : IJobParallelFor {
    public float deltaTime;
    public NativeArray positions;
    public NativeArray velocities;

    public void Execute(int index) {
        positions[index] += velocities[index] * deltaTime;
    }
}
上述代码中,Execute 方法由多个工作线程并发调用,每个线程处理数组中的一个元素。deltaTime 作为只读参数被所有线程共享,而 positions 和 velocities 以原生数组形式传入,避免了 GC 开销。
性能增强:Burst 编译器
Burst 编译器将 C# Job 代码编译为高度优化的 SIMD 汇编指令,显著加速数学运算。启用方式只需添加 [BurstCompile] 特性:
  • 自动向量化循环操作
  • 深度内联与死代码消除
  • 精确的浮点控制提升数值稳定性

4.4 封装通用协程调度器实现精细化控制

在高并发场景下,协程的无序创建可能导致资源竞争和上下文切换开销。通过封装通用协程调度器,可实现对协程生命周期与执行顺序的精细化控制。
核心设计思路
调度器需具备任务队列管理、并发度控制和错误恢复能力。采用带缓冲通道作为任务队列,限制最大协程数,避免系统过载。

type Scheduler struct {
    workers int
    tasks   chan func()
}

func NewScheduler(workers int) *Scheduler {
    return &Scheduler{
        workers: workers,
        tasks:   make(chan func(), 100),
    }
}

func (s *Scheduler) Run() {
    for i := 0; i < s.workers; i++ {
        go func() {
            for task := range s.tasks {
                task()
            }
            }()
    }
}
上述代码中,workers 控制并发协程数量,tasks 缓冲通道存储待执行任务。调用 Run() 后,启动固定数量的工作协程从队列消费任务,实现可控的并发执行模型。

第五章:构建流畅游戏体验的协程治理全景图

协程生命周期的精细化控制
在Unity等主流游戏引擎中,协程常用于处理异步加载、动画序列与网络请求。为避免内存泄漏,必须在对象销毁时显式终止协程:

IEnumerator LoadSceneAsync() {
    yield return new WaitForSeconds(1f);
    AsyncOperation op = SceneManager.LoadSceneAsync("Level1");
    while (!op.isDone) {
        loadingBar.fillAmount = op.progress;
        yield return null;
    }
}

// 安全启动与终止
Coroutine loadRoutine = StartCoroutine(LoadSceneAsync());
StopCoroutine(loadRoutine); // 或使用StopAllCoroutines()
协程调度策略对比
不同场景需匹配合适的调度机制:
  • 帧同步协程:每帧执行一次,适用于UI刷新
  • 时间延迟协程:基于真实时间或游戏时间,适合倒计时逻辑
  • 事件驱动协程:结合C#事件模型,在特定条件触发后继续执行
异常处理与资源清理
协程内部异常不会自动抛出到主线程,需手动捕获:

try {
    yield return StartCoroutine(NetworkRequest());
} catch (System.Exception e) {
    Debug.LogError($"Network error: {e.Message}");
} finally {
    isLoading = false;
}
性能监控与可视化分析
通过自定义协程管理器追踪运行状态:
指标建议阈值优化手段
并发协程数< 50池化复用,限制并发量
单次执行耗时< 16ms分帧处理,拆解长任务
Unity协程(Coroutine)管理类——TaskManager工具分享 NULL 博文链接:https://dsqiu.iteye.com/blog/2022992 立即下载

相关推荐

国央企创新负责人如何通过平台实现科研成果的快速识别与转化?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

协程是怎么实现的,如何用纯C#怎么实现协程,协程和线程的区别

在上面的代码中,CoroutineExample类是一个协程管理器,通过Start()方法来启动协程的执行,通过Stop()方法来停止协程的执行,通过Resume()方法来恢复协程的执行。在Resume()方法中,使用while循环来遍历协程中的yield语句,如果协程被暂停或已经执行完毕,则跳出循环。在上面的代码中,MyCoroutine()方法是一个协程,使用StartCoroutine()方法来启动协程的执行。在MyCoroutine()方法中,使用yield return语句来暂停协程的执行。

無限進步的全棧遊戲開發的博客 3638

如何点亮一颗sensor

要点亮一个sensor需要从,时钟、sensorI2C,供电,reset脚,mipi的配置几个方面一一确认。 reset脚拉高 给sensor的时钟有没有。(目前用到的常为24MHZ) 供电 查看sensor的数据手册,看有几个电源,用示波器量一下是否为手册规定的电压 比如:DVDD 数字电压: AVDD模拟电压 DOVDD芯片引脚出来的电压等为多少。 sensor的I2C能否抓到 将I2C的口对应上,用示波器量取i2c的波形。 检查有应答并且数据正确。读写地址是否正...

weixin_40787463的博客 3646

Unity中协程(IEnumerator)的使用

当我们的任务不能在一帧之内完成,而需要持续一段时间的时候,需要用一种方式将进程从主线程中剥离,放在另一条分支上(伪)。创建协程后,通过StartCoroutine()来调用协程函数,函数内部则通过yield来挂起函数,让函数等待下一次调用。效果实现了,但是问题也来了:这药水效果一直存在,砍谁都是一刀斩了!这样咱们大力药水不消褪的问题就解决了,只要在获得buff后开启协程,在协程结束后将效果取消即可,代码如下。协程使得方法的状态被存储了,方法中定义的这些变量都会保存它们的值,即使是在不同的帧中。

qq_53226385的博客 2207

Diffusion Model进阶解析:从SDE到概率流ODE的连续化生成建模

本文深入解析了Diffusion Model的连续化生成建模,从离散DDPM和SGM模型引入,阐述了采用随机微分方程(SDE)统一视角的必要性与优势。文章详细拆解了SDE的构成,揭示了其如何统一描述扩散过程,并重点介绍了逆向SDE与确定性的概率流ODE,后者为高效、确定的图像生成提供了理论基础。最后,文章对比了朗之万动力学、数值SDE求解器和数值ODE求解器(如DPM-Solver)等主流采样方法的实战应用与选择策略。

weixin_29099217的博客 437

手眼标定(EyeToHand)推导

Base为基坐标系(B),工具末端坐标系(T),标定板为Mark坐标系(M),相机坐标系(C)对于每两个姿态都存在上式,组成一个AX=XB的矩阵方程,X为。此时转换成AX=0的问题,单纯用SVD求奇异解便可得到。相机坐标系到Base基坐标系下的转换关系。已知标定板与机械臂末端的相对位置固定不变,,即。带入(2)式求,至此求解出需要的手眼矩阵。在眼在手外的时候,其实是要求解。

stevenreally6的博客 1143

Unity协程完全指南:十万字从入门到精通

Unity协程完全指南:十万字从入门到精通

不定时分享所学所得,包括游戏开发和其他收获! 1888

从Level 1到Level 22:手把手带你用Burp Suite通关burp-labs靶场全关卡(附难点解析)

本文详细解析了如何使用Burp Suite通关burp-labs靶场的22个关卡,从基础爆破到复杂编码绕过,涵盖Intruder配置、响应过滤、POST请求处理、MD5爆破等关键技术。特别针对Level 16的三重编码和Level 20的中文响应处理等难点提供实战技巧,帮助渗透测试工程师提升Web安全实战能力。

weixin_28831461的博客 435

Unity实用框架(二)协程管理框架

C# unity自带的Coroutine提供了最基础的使用协程的接口,在此基础上,笔者将提供一种能够适用于更多场景、更容易由程序员全权控制的协程管理框架.

natrick的博客 1739

AI+Xmind自动生成测试用例(思维导图格式)

最后:我是Walker,一个热爱分享编程知识的程序员,希望能够帮助到你!

Think_and_work的博客 2333

innovus:sroute 双层follow pin的做法

根据std cellpower pin的层次可以分成两种情况。

m0_61544122的博客 2731

Time.timeScale对性能消耗的影响

在Unity中,控制的是游戏逻辑中时间流逝的快慢,而不是实际的帧率。当Time.timeScale的值改变时,它影响的是Time.deltaTime和Time.fixedDeltaTime这两个值,它们分别表示自上一帧以来经过的时间(对于Update和LateUpdate)和固定时间步长(对于FixedUpdate)。

2301_76618920的博客 1443

RK3568平台(网络篇)WIFI模块RTL8821CU调试

RTL8821CU是瑞昱半导体推出的usb接口的wifi,下面的教程将介绍如何将RTL8821CU移植到rk3588的平台上。移植usb wifi需要修改的文件Android hal层需要修改的文件//kernel需要修改的文件kernel/arch/arm64/boot/dts/rockchip/rk3399-tve1030g.dtsi //除去板上的sdio的wifi。

weixin_49303682的博客 3904

Unity/C# 关于协程

··协程方法被调用时,Unity会将协程与一个迭代器一起添加到待处理队列; Unity将在每一帧的Update方法中处理队列中的协程,直到协程完成或被停止。··通过 IEnumerator 接口实现,利用 yield 语句在特定位置暂停执行,并通过MoveNext()方法恢复执行。 -迭代器与 IEnumerator :Unity通过遍历 IEnumerator 对象实现协程的分步执行; -协程调度器:Unity内置的协程管理器负责跟踪所有协程状态,在每帧检查每个协程的条件是否满足(如等待时间是否到达)。用

PROMISEa的博客 453

独家改进|基于YOLO26的轻量级检测网络:参数量减半,精度不降反升

不要全层替换深度可分离卷积:P5深层对语义特征要求高,用标准卷积效果更好,只在P2、P3浅层用DWConv性价比最高注意力不是越多越好:每个阶段加一个就够,加在模块输出端,不要插在模块中间,否则部署容易出现算子不兼容问题轻量模型训练别贪快:初始学习率一定要调低,不然很容易前期震荡,后期收敛不上,精度卡在瓶颈小目标场景优先保留P2分支:如果对速度要求不是极致,保留P2检测头,小目标收益远大于速度损失。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 221

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

C# 游戏引擎中的协程

简单来讲,协程是轻量级,用户级的线程,通过“分时复用” 的方式模拟多线程操作。协程是一个“伪线程”,它其实只在一个线程上执行,但是通过执行“挂起”和“恢复”等操作,可以实现“不同时间执行不同任务”或者说“一个任务分到多个帧内完成”。协程的优点就是缺点,缺点就是优点。它没有直接操作线程繁琐,也无法发挥多核处理器的优势,所以它并非“必要的”。不过对于游戏开发而言,游戏一般只有一个“主循环”,或者说一个主要线程,所以资源和数据(也可以说“上下文”(context))主要就只在一个线程中。

m0_73087695的博客 3924

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【Unity性能优化秘籍】:用好IEnumerator协程提升游戏流畅度

掌握Unity C# 协程 IEnumerator 用法,有效解决游戏卡顿问题。通过yield return实现异步加载、延时执行与资源调度,提升运行流畅度。详解协程核心机制与性能优化技巧,适用于动画控制、关卡加载等场景,值得收藏。

ByteShoal的博客 856

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

GC垃圾回收机制

托管堆:由Mono分配与管理。而托管的 意思是可以自动改变堆的大小,适应内存的需要,适合时机调用GC释放内存。 Unity内存管理机制 1、Unity存在2个内存管理区域,堆和堆栈,堆栈一般存储小和短暂的数据,堆存储大和时间长的数据 2、堆和堆栈之间差异:堆栈分配与回收较快。而堆在分配内时,先检查是否有内存,如果没有,将会进行GC,堆在GC后内存仍然不足时,将会申请内存,但是GC所释放的内存,将...

Ha啤酒来大杯的博客 396

协程管理工具

这个工具是本人基于TaskManager改动来的 通过两个脚本来对协程进行管理 1.TaskManager 这个脚本主要用来控制Task,包括添加,开启,获取Task的状态等等,只需要输入Task对应的名称,即可进行相关的操作 using System.Collections; using System.Collections.Generic; using System.Linq; using S...

qq_42438256的博客 330

Unity中协程的作用和使用方法

协程,即Coroutine,可以认为它是一个返回值是IEnumerator的函数,但是使用它需要配合StartCoroutine使用。 协程不是多线程,所有的任务还是在主线程上完成,是一种异步多任务处理的方式。 协程的好处在于,它可以在一个函数内实现像update那样按帧执行某个部分,或者按照过几秒后执行某个部分。 例如实现一个计时器: 普通的实现方式如下: 这种方法有两个弊端,在每一帧都需要判断执行一次,浪费资源。 创建很多变量,实际上只改变了一个数字。 对比使用协程的方法: yield retur

weixin_43757333的博客 1万+

Unity协程(一):彻底了解yield return null 和 yield return new WaitForSeconds

unity的协程毫无疑问是个非常棒的设计,但是也存在着一些坑和一些误区。

fdyshlk的博客 6万+

Unity 协程

延迟函数: Destroy(object,float time);time时间之后销毁object类型; Invoke延迟执行函数,通过方法名延迟调用对应函数; 注意:当此脚本或者当前脚本所在的游戏物体失活,延迟函数依然会执行; 但是当前脚本或者游戏物体被销毁,延迟...

weixin_30648963的博客 396

【Unity】 C# 协程 WaitForSeconds产生GC(Garbage Collection)问题

原文链接:http://blog.youkuaiyun.com/u010019717/article/details/44948903孙广东 2015.4.9 24:00 先来看看使用协程的作用一共有两点: 1)延时(等待)一段时间执行代码; 2)等某个操作完成之后再执行后面的代码。总结起来就是一句话:控制代码在特定的时机执行。 协程不是线程,也不是异步执行的。协程和 MonoB

RICKShaozhiheng的专栏 4146
上一篇: 资深架构师亲授:如何在生产环境中高效使用Valgrind避免内存泄漏?
下一篇: 从零开始掌握C#调用C++ DLL:5大关键步骤与避坑指南
codetrick
博客等级 码龄17年 151粉丝 1991原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值