2021-11-05-golang内存分配

最新清华老师把《GO内存管理》讲的明明白白(2),2024年最新Golang性能优化常见问题 我们寻找_k_自由列表中的第四项,其中包括_k_如果是空的我们就下去。冲洗并重复,直到_128_数组条目如果我们找不到空页_127_,我们在剩余的大页中寻找一个跨度(mspan.freelarge(字段),如果失败,我们从OS获取。通常,您用高级语言编写程序,如GO,这些语言被编译成可执行的机器代码文件或不可执行的机器代码对象文件(库)。当您需要的内存量,或者您继续需要它的时间,取决于程序运行之前不知道的因素时,您需要动态分配。在这个例子中,_跨度1_占用2页,_跨度2_占据了4页,_跨度3_占据1页。 阅读详情

简介

最近被golang的内存问题困扰,这里做一下功课,将通过收集资料,记录笔记的方式将golang的内存分配相关知识搞清楚。资料来自于阅读《go语言学习笔记》,源码,网上的资料。

大事件

2014/06 go 1.3: 并发清理
2015/08 go 1.5: 三色并发标记

基础数据结构、概念

STW(Stop The Word)

在垃圾回收算法中,Stop The Word(STW)是一个很重要的概念,他会中断程序运行,添加写屏障,以便扫描内存 ,现在一起来看看它内部的原理以及可能存在的问题。并行清理是指垃圾回收和用户逻辑并发执行。

流程

golang源码注释

mgc说明

gc源码位置:Go\src\runtime\mgc.go。在它的源码的注释里面写了大段关于内存回收相关知识。下面是翻译。

GC 与 mutator 线程并发运行,类型准确(又名精确),允许多个GC 线程并行运行。 它是使用写屏障的并发标记和清除。 这是非分代和非压缩。 分配是使用每个 P 分配隔离的大小完成的在常见情况下消除锁定的同时最小化碎片的区域。

算法分解为几个步骤。

这是正在使用的算法的高级描述。 对于 GC 的概述,一个很好的入门是 Richard Jones 的 gchandbook。

  1. GC 执行扫描终止。

    a. 停止世界。 这会导致所有 P 达到 GC 安全点。

    b. 扫描任何未扫描的跨度。 只有在以下情况下才会有未扫过的跨度在预期时间之前强制执行此 GC 循环。

  2. GC 执行标记阶段。

    a. 通过将 gcphase 设置为 _GCmark 来准备标记阶段
    (来自_GCoff),启用写屏障,启用mutator
    协助和排队根标记作业。没有对象可以
    扫描直到所有 Ps 都启用了写屏障,即
    使用 STW 完成。

b. 开始世界。从这点来说,GC工作由mark来完成
由调度程序启动的工作人员和由执行的协助
部分分配。写屏障遮蔽了
覆盖指针和任何指针的新指针值
写入(有关详细信息,请参阅 mbarrier.go)。新分配的对象
立即被标记为黑色。

c. GC 执行根标记作业。这包括扫描所有

堆栈,对所有全局变量进行着色,并对其中的任何堆指针进行着色
堆外运行时数据结构。扫描堆栈停止
goroutine,将在其堆栈中找到的任何指针着色,然后
恢复 goroutine。

d. GC 排空灰色对象的工作队列,扫描每个灰色对象
将对象变为黑色并对在对象中找到的所有指针进行着色
(反过来可能会将这些指针添加到工作队列)。

e.因为 GC 工作分布在本地缓存中,所以 GC 使用
分布式终止算法来检测何时没有
更多根标记作业或灰色对象(参见 gcMarkDone)。在这
点,GC 过渡到标记终止。

  1. GC 执行标记终止。

    a. 停止世界。

    b. 将 gcphase 设置为 _GCmarktermination,并禁用 worker 和 辅助。

    c.执行内务处理,如刷新 mcaches。

  2. GC 执行扫描阶段。

    a. 通过将 gcphase 设置为 _GCoff 来准备扫描阶段, 设置扫描状态并禁用写屏障。

b. 开始世界。从现在开始,新分配的对象
是白色的,如有必要,在使用前分配扫描跨度。

c. GC 在后台和响应中进行并发扫描

分配。请参阅下面的说明。

  1. 当足够的分配发生时,重放序列
    从上面的 1 开始。请参阅下面对 GC 率的讨论。

并发扫描。

扫描阶段与正常程序执行同时进行。
堆被一个跨跨度地懒惰地扫过(当一个 goroutine 需要另一个跨度时)
并在后台 goroutine 中并发(这有助于不受 CPU 限制的程序)。
在 STW 标记终止结束时,所有跨度都被标记为“需要清除”。

后台清扫器 goroutine 只是一一扫过 span。

为了避免在有未扫描跨度时请求更多操作系统内存,当
goroutine 需要另一个跨度,它首先尝试回收那么多内存
通过清扫。当一个 goroutine 需要分配一个新的小对象跨度时,它
扫描相同对象大小的小对象跨度,直到它至少释放
一个对象。当一个 goroutine 需要从堆中分配大对象跨度时,
它会扫描 span,直到将至少那么多页释放到堆中。有
这可能不够的一种情况:如果一个 goroutine 清除并释放两个
不相邻的一页跨越到堆,它将分配一个新的两页
跨度,但仍然可以有其他一页未扫过的跨度
合并成一个两页的跨度。

确保没有操作在未扫描的跨度上继续(这会破坏 在 GC 位图中标记位)。在 GC 期间,所有 mcache 都刷新到中央缓存中, 所以它们是空的。当一个 goroutine 将一个新的跨度抓取到 mcache 中时,它会清除它。 当一个 goroutine 显式地释放一个对象或设置一个终结器时,它确保 扫描跨度(通过扫描它或等待并发扫描完成)。 只有当所有跨度都被扫描时,终结器 goroutine 才会启动。 当下一次 GC 开始时,它会扫描所有尚未扫描的跨度(如果有)。

垃圾回收率。

下一次 GC 是在我们分配了与已经使用的数量。比例由GOGC环境变量控制(默认为 100)。如果 GOGC=100 并且我们使用的是 4M,当我们达到 8M 时我们会再次 GC(此标记在 gcController.heapGoal 变量中跟踪)。这将 GC 成本保持在与分配成本成线性比例。调整GOGC只是改变线性常数(以及使用的额外内存量)。

小物件

为了防止在扫描大对象时出现长时间的停顿并
提高并行性,垃圾收集器将扫描作业分解为
大于 maxObletBytes 的对象最多变成“oblets”
maxObletBytes.当扫描遇到大的开头
对象,它只扫描第一个 oblet 并将剩余的排入队列
oblets 作为新的扫描作业。

mstats说明

内存分配

制作了预分配、内存池操作。

分配大概流程

内存分配只关心内存块,不关心对象状态。不会主动发起内存回收,垃圾回收器完成清理工作后,触发内存分配器的回收操作。

  1. 每次从操作系统申请大块内存,减少系统调用;
  2. 将内存块按照预先的大小切分成小块,够造成链表;
  3. 分配对象内存的时候,从大小合适的链表中提取一块小块使用;
  4. 回收对象内存时,将此对象重新归还到合适的链表中;
  5. 如果闲置内存过多,尝试将归还部分内存给操作系统;
内存块

分配器只有两种逻辑块。

span:由多个地址连续的页(page)组成的大块内存。
object:将span按照特定大小切分成小块,用于保存object。

按照用途来分,span是提供分配器内部使用,object是面向外部分配提供的。

span中的size也会更具实际情况做裁剪,或者归还给系统。对应的代码位置:malloc.go,mheap.go。

存储object的空间按照8字节对齐。底层制作了分配class的映射表,超过32kb的object将会当成 large object 对待。

三色标记和写屏障

  1. 开始全部为白色;
  2. 扫描出全部可达对象,标为灰色,写入待处理队列;
  3. 从队列提取会随对象,将其引用对象标记灰色,放入队列,自己标记为黑色;
  4. 写屏障监视对象内存修改,重新标色或者放回对了;
  5. 完成上述工作后,只有黑白两色,黑色全部回收。

控制器 gcControoler

控制器会参与回收任务,记录状态数据,动态调整运行策略,影响并发标记单元的工作模式和数量,平衡CPU资源占用。回收结束之后,参与next_gc回收阈值设置,调整垃圾回收出发频率。

测试数据

测试两份内存web数据,heap的dump信息。

如何阅读heap信息

golang中的MemStats数据结构是用于描述当前进程的内存消耗值。

概要统计信息

Alloc 分配给heap对象的内存大小。这个值和HeapAlloc相同。

TotalAlloc 累计分配给heap对象的内存大小。它的增长和Alloc是一样的,但是不会随着对象释放而降低。

Sys 从OS获取的全部内存大小。这个值就是下面XSys值的总和。Sys度量被Go的运行时使用的一些虚拟地址空间,用于存储heap,stacks,和其他的内部数据结构。 虚拟内存不会真实的分配物理内存,虽然通常这一切是在某个时刻发生。

Lookups 处理runtime时候使用的指针数量。通常用于运行时调试之用。

Mallocs 累计分配heap对象个数。还存活的对象数量就是Mallocs - Frees

Frees 累计释放heap对象个数。

堆统计信息
简介信息

介绍一些Go如何组织内存。Go分割heap的虚拟内存到spans,这种内存是连续区域的内存大小在8k或者更加大。一个span可能有下列3中状态:

idle容器中没有任何的对象或者数据。idle span背后的物理内存能被释放还给OS(但是虚拟地址空间并不会这么做),或者能被转换成in use或者stack span。

in use至少含有一个heap对象而且可能含有空闲的空间提供分配给heap对象。

stack span 提供给了goroutine 栈使用。栈span不会被视为堆的一部分。span可以被当成heap或者stack内存;但是不可能同时用于两种。

细则

HeapAlloc heap对象分配时使用的内存大小。分配的heap对象包含一切能被引用的的对象,也包含没有被引用还没有被GC回收的对象。特别的,HeapAlloc增长时伴随着heap对象的分配,降低时伴随heap内存清理和没被引用的对象被回收。清理渐进的发生于GC周期,所以二者处理都是同时在进行中,最终HeapAlloc的结果趋近于平滑(于之形成对比的锯齿的情况,发生在stop-the-world内存回收过程)。

HeapSys heap对象从OS分配内存空间。HeapSys度量的是heap使用的虚拟内存空间。这些虚拟机空间已经被分配,但是没有使用,这样的情况将不会消耗任何的物理内存,但是它变成未使用时(阅读等下将提到的HeapReleased量),当值将会变小,这种情况发生在虚拟内存对应的物理内存归还给OS。

HeapIdle idle spans的空间。里面没有任何的对象,这些span可以(或者已经)被归还给OS,或者他们可能被提供给heap分配器接着来分配,或者也可以提供给stack做内存。HeapIdle减去HeapReleased就等于将会归还给OS的空间,但是这块空间可能被runtime利用,以便于heap变大时候,无需再次从OS中申请更多内存。如果这个差值大于heap大小,预示着最近有一次瞬时的实时堆大小达到的峰值。

HeapInuse in-usespans占用的空间大小。至少有一个对象在这里。这种span只能被用于相同的内存尺寸对象的分配。HeapInuse-HeapAlloc等于当前还可以分配给特定尺寸对象内存量,但目前尚未使用到。这个是内存碎片的上限,但是通常这么做能更加高效的复用。

HeapReleased 归还给操作系统的物理内存。从idle spans归还给操作系统的总数内存块,尚未为堆重新获取。

HeapObjects 当前分配的heap对象数目。和HeapAlloc相似,此值增减发生在对象分配和堆整理而且不可达对象的清理。

栈信息

堆和栈内存是互相独立的,在go运行时中,能将二者的内存互相转换。

细则

StackInuse 栈spans中使用全部内存块

StackSys 栈从OS中获取的内存块。StackSys是StackInuse加上少量直接从系统获取的空间为系统级线程的栈。

非堆栈内存信息

下面部分是运行时内部的数据结构的内存使用情况,未从堆内存分配的结构(通常是因为它们是实现堆的一部分)。不像堆或者栈内存,这种内存有专属的数据结构。

这些内存主要用于调试运行时内存。

细则

MSpanInuse / MSpanSys 分配mspan的内存,从系统中获取的空间。

MCacheInuse / MCacheSys 分配mcache的内存,从系统中获取的空间。

BuckHashSys 分析hash桶表大小。

GCSys gc元数据。

OtherSys 杂项。

为了方便,我写了一个读取的脚本。源码下载地址

这里我分析了一份内存:

概要信息
------------------
堆使用空间: 1.2G
累计分配堆空间: 10.3G
从系统分配的虚存: 0B
堆累计分配obj个数: 228.4M
堆累计归还obj个数: 213.1M
存活obj个数: 15.3M


堆信息
------------------
堆span空间中被obj用的空间: 1.2G
堆span累计空间: 1.8G
堆空闲span空间: 428.6M
堆span的全部空间: 1.4G
堆span中obj碎片空间: 188.1M
从堆span归还给OS空间: 1000.0K
当前内存中obj个数: 15.3M
全部堆内存使用: 1.8G


栈信息
------------------
栈spans中使用全部内存块: 1.3M
栈从OS中获取的内存块: 1.3M


非堆栈内存
------------------
mspan使用内存: 23.5M
mspan从OS中获取的内存块: 30.2M
mcache使用内存: 4.7K
mcache从OS中获取的内存块: 16.0K
分析hash桶表大小: 1.6M
gc元数据: 81.9M
杂项: 4.2M

heap分布I3FDiD.png

引用

图解Golang的内存分配 一般程序的内存分配 在讲Golang的内存分配之前,让我们先来看看一般程序的内存分布情况: 以上是程序内存的逻辑分类情况。 我们再来看看一般程序的内存的真实(真实逻辑)图: Go的内存分配核心思想 Go是内置运行时的编程语言(runtime),像这种内置运行时的编程语言通常会抛弃传统的内存分配方式,改为自己管理。这样可以完成类似预分配、内存池等操作,以避开系统调用带来的性能问题,防止每次分配内... 阅读详情

相关推荐

SAP MM采购合同创建全解析:ME31K操作与后台逻辑

在SAP ERP的物料管理模块中,采购合同作为框架协议的核心,定义了企业与供应商之间的长期供货关系。它与采购订单不同,合同不直接产生收货或发票,而是为后续采购订单提供数据源。创建合同(事务码ME31K)时,需要区分数量合同与金额合同,并维护抬头、行项目、有效期、价格条件和税码等关键信息。SAP通过源确定机制在创建采购订单时自动匹配合同,同时审批策略、编码范围和输出类型也会影响合同的实际可用性。掌握合同创建逻辑,能有效解决采购订单无法带出合同、审批未触发、价格缺失等高频问题。从ME31K实操出发,系统梳理采购

weixin_30000735的博客 196

Golang内存调试与CPU性能分析

如何分析程序的运行时间 time指令 time go run main.go real 从程序开始到结束,实际上度过的时间 user 程序在⽤户态度过的时间 程序在内核态度过的时间 ⼀般情况下 real>= user + sys /usr/bin/time指令 可以看到CPU占⽤率、内存的使⽤情况、进程的切换情况、⽂件系统IO、socket情况等 如何分析Golang程序的内存使用情况 内存的占用情况 top -p $(pidof 进程名) mem 总体内存情况 f

weixin_44879611的博客 1079

嘉立创EDA vs Altium Designer:新手如何选择?从界面到实战全对比

本文全面对比了嘉立创EDA与Altium Designer(AD)两大PCB设计工具,从设计哲学、界面交互、封装库管理、设计规则引擎、协作功能到成本生态六大维度进行深入分析。嘉立创EDA以极简设计和云端协作为特色,适合学生和创客快速上手;而AD则凭借专业级精准控制,成为高端电子设计的行业标准。通过实战案例和详细对比表格,帮助新手根据项目需求选择合适的EDA工具。

weixin_30296405的博客 721

Java中的OutOfMemoryError的各种情况及解决和JVM内存结构

在JVM中内存一共有3种:Heap(堆内存),Non-Heap(非堆内存) [3]和Native(本地内存)。 [1] 堆内存是运行时分配所有类实例和数组的一块内存区域。非堆内存包含方法区和JVM内部处理或优化所需的内存,存放有类结构(如运行时常量池、字段及方法结构,以及方法和构造函数代码)。本地内存是由操作系统管理的虚拟内存。当一个应用内存不足时就会抛出java.lang.OutOfMemoryError 异常。 [1] 问题 表象 诊断工具

srs1995的博客 1089

Sonatype nexus3 数据迁移及升级3.71+(迁移到H2数据库)

nexus3旧版本OrientDB升级H2,及整体迁移nexus3数据到其它服务器。

葫芦娃 5553

Agent应用实践之三 - 基础:AgentScope-ReActAgent源码解析

本章通过总结AgentScope的核心类,再通过分析ReActAgent调用大模型的底层源码原理。使我们基本了解了Agent的基本原理,这个实现方式与OpenClaw使用pi-mono的Agent基础框架是一致的。了解完ReActAgent的基本原理,下一章我们会将一下SpringBoot集成方式的代码原理,这两章是我们构建后续内容的基本框架。

代码让AI扣 469

Golang中的CPU占满100%及解决方案

Golang中的CPU占满100%及解决方案 有一个流媒体适配服务,出现了CPU开销很大的问题,一个服务把CPU资源占满了,导致其他服务无法正常工作。 下面来详细记录发现bug和解决的流程。 发现CPU开销很大 扫描发现,是垃圾回收导致CPU使用上升 : Time: Mar 22, 2019 at 5:52pm (CST) Duration: 1mins, Total samp...

u010412301的博客 5439

Kylin操作系统下OpenLDAP安装

Kylin操作系统下OpenLDAP安装

跟着大数据和AI去旅行 1612

JavaScript中的 CORS问题

CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。 浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。 服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。 虽然设置 CORS和前端没什么关系,但是通过这种方式解决跨域问题的话,会在发送请求时出现两种情况,分别为简单请求和复杂请求。 .

LuckXinXin的博客 1489

X电容与Y电容,看这一篇就够了

本文详细介绍了X电容与Y电容的定义、作用、位置、分类,以及它们在实际应用中的容值选取和计算方法。通过汽车电子应用和X电容放电电路的实例,帮助读者深入理解这两种安规电容的重要性。文章还探讨了电容放电电阻的计算,确保符合安全规范。

让你爱上电路设计 7017

[特殊字符] PetaLinux Qt 程序(WindRadar)无法自动启动问题解决文档

摘要:本文档解决了PetaLinux 2020.1系统中Qt程序(WindRadar)无法开机自动显示界面的问题。通过分析发现,自动启动时缺少DISPLAY=:0.0环境变量导致Qt找不到显示设备。最终在autostart.sh脚本中添加该变量,并完善了字体加载、驱动加载、显示设备检测等流程,确保程序正常自启显示界面。完整脚本包含路径检测、环境配置和错误处理,经验证各项功能均正常运行。

梁俊星的博客 326

Go进程的HeapReleased上升,但是RSS不下降造成内存泄漏?

事情是这样的,线上一个服务,启动后RSS随任务数增加而持续上升,但是过了业务高峰期后,任务数已经下降,RSS却没有下降,而是维持在高位水平。 那内存到底被谁持有了呢?为了定位问题,我把进程的各项Go runtime内存指标,以及进程的RSS等指标持续采集下来,并以时间维度绘制成了折线图: 内存折线图 本着DRY原则,我把采集和绘制部分专门制作成了一个开源库,业务方代码可以十分方便的接入,绘制出如上样式的折线图,并通过网页实时查看。git地址:https://github.com/q191201771/p

猛犸象 1721

【Proteus仿真】基于74LS148+74LS279+74LS48的四路抢答器

【Proteus仿真】基于74LS148+74LS279+74LS48的四路抢答器

perseverance51博客 8833

golang/go 内存分配流程

go进程在内存不足时一次向操作系统申请一个heapArenaBytes(linux amd64位操作系统为64M,下文的数据默认说的都是linux amd64位操作系统数据)。为了高效的实现内存操作,Golang在堆mheap之上,建立了mcentral,mcache的模型,内存申请时锁级别也由无所到分级锁再到全局锁。golang/go中按照不同大小的对象,将mspan从8B到32K(大于32K的在mspan class为0的mspan中,不固定大小)划分为不同级别,以便实现不同级别的对象的精细化管理。

lennonchan的专栏 933

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

深度学习工具包 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")

Go 内存分配

转载: 图解Golang的内存分配: https://i6448038.github.io/2019/05/18/golang-mem/ 文章目录1 Go的内存分配核心思想2 Go的内存结构2.1 arena2.2 spans2.3 bitmap3 内存管理组件3.1 mspan3.2 mcache3.3 mcentral3.4 mheap4 Go内存分配流程总结4.1 对象分三种:4.2 分配顺序 1 Go的内存分配核心思想 Go是内置运行时的编程语言(runtime),像这种内置运行时的编程语言通常会抛

随心的专栏 1110

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

golang内存分配概述

golang内存分配概述 golang的内存分配机制主要类似于tcmalloc机制,来快速高效的分配与管理内存,从而高效分配与管理内存。 有关 tcmalloc 的详细资料大家可参考官网,简单概括就是通过预先分配一个大的堆,每个线程都管理一块小内存的对象列表,大对象都是直接通过堆来直接管理,每个线程申请内存的时候如果小对象就直接在堆上分配,大对象就通过堆分配,每个内存都可以再堆上管理到。大家有兴趣课详细看一个官网的介绍,golang的内存分配也是按照如上原理来实现的,大概了解了tcmalloc的流程就很好理

qq_33339479的博客 1034

Go 中的内存分配

1、概述 内存分配的基本策略: 每次从操作系统申请一大块内存(比如1MB),以减少系统调用。 将申请到的大块内存按照特定大小预先切分成小块,构成链表。 为对象分配内存时,只须从大小合适的链表提取一小块即可。 回收对象内存时,将该小块内存重新归还原链表,以便复用。 如闲置内存过多,则尝试归还部分内存给操作系统,降低整体开销。 内存块 分配器将其管理的内存块分为两种。 span: 将多个地址连续...

wymyimeng的博客 369

Go技术日报(2021-11-24——28)——雷军做程序员时写的博客

每日一谚: Picard engineering tip: Use the metric system. go中文网每日资讯--2021-11-27/28 一、Go语言中文网 用泛型实现 Result 类型处理 error Go语言爱好者周刊:第 121 期 让flag支持从文件中读取命令行参数 Go:Recover 那些事 使用Docker Compose构建一键启动的运行环境 二、幼麟实验室 【Golang】堆内存分配mallocgc 三、MoeLove 新功能:Prometheus Ag.

韩亚军的博客 4285

图解Golang的内存分配https://mp.weixin.qq.com/s/pbwCYFEESkILGIJVqnNaLA

一般程序的内存分配 在讲Golang的内存分配之前,让我们先来看看一般程序的内存分布情况: 以上是程序内存的逻辑分类情况。 我们再来看看一般程序的内存的真实(真实逻辑)图: Go的内存分配核心思想 Go是内置运行时的编程语言(runtime),像这种内置运行时的编程语言通常会抛弃传统的内存分配方式,改为自己管理。这样可以完成类似预分配、内存池等操作,以避开系统调用带来的性能问题,...

小豆角的博客 822

Golang内存管理——堆分配

内存分配是Go语言的基础,涉及的内容比较多,关联操作系统、用户程序、GC垃圾回收等部分,是一个大难点。

wangye135的博客 1366

【Go语言-Day 11】深入浅出Go语言数组(Array):从基础到核心特性全解析

在Go语言中,数组的设计有着独特的哲学,尤其是其“值类型”的特性,常常是新手乃至进阶者容易忽视的“陷阱”。本文将带你从数组的定义与初始化,到其核心特性(长度与类型、值传递),再到多维数组和实际应用,系统性地为你揭开Go语言数组的神秘面纱。

吴师兄大模型的博客 1786

Golang sync.Pool 快速上手

Pool 是可伸缩、并发安全的临时对象池,用来存放已经分配但暂时不用的临时对象,通过对象重用机制,缓解 GC 压力,提高程序性能。 一个比较好的例子是 fmt 包,fmt 包总是需要使用一些 []byte 之类的对象,Golang 建立了一个临时对象池,存放着这些对象,如果需要使用一个 []byte,就去 Pool 中取,如果拿不到就分配一个。这比起不停生成新的[]byte,用完了再等待 GC 回...

Doublelv 的博客专栏。 5974

【Go】strings.Replace 与 bytes.Replace 调优

原文链接:https://blog.thinkeridea.com/201902/go/replcae_you_hua.html 标准库中函数大多数情况下更通用,性能并非最好的,还是不能过于迷信标准库,最近又有了新发现,strings.Replace 这个函数自身的效率已经很好了,但是在特定情况下效率并不是最好的,分享一下我如何优化的吧。 我的服务中有部分代码使用 strings.Replace ...

戚银的博客 1159
上一篇: go-etcd阅读笔记
下一篇: 2020-11-21-卡农吉他谱
erlang_hell
博客等级 码龄14年 57粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值