从零理解Go的atomic包:彻底搞懂CompareAndSwap与Load/Store操作

golang:atomic.Pointer go语言标准库sync/atomic 的原子性操作 阅读详情

第一章:从零开始理解Go的atomic包核心概念

在并发编程中,多个goroutine同时访问共享资源可能导致数据竞争和不可预测的行为。Go语言通过`sync/atomic`包提供原子操作支持,确保对基本数据类型的读写具备原子性,从而避免使用互斥锁带来的性能开销。

原子操作的基本类型

`atomic`包主要支持对整型(int32、int64)、指针、布尔值等类型的原子操作。常见的操作包括:
  • atomic.LoadXXX:原子读取值
  • atomic.StoreXXX:原子写入值
  • atomic.AddXXX:原子增加
  • atomic.CompareAndSwapXXX:比较并交换(CAS)

Compare-and-Swap 的典型应用

CAS是实现无锁并发结构的基础。以下代码演示如何使用CAS安全地更新计数器:
// 定义一个需要原子操作的整型变量
var counter int32

// 在多个goroutine中安全递增
func increment() {
    for {
        old := counter
        if atomic.CompareAndSwapInt32(&counter, old, old+1) {
            break // 成功更新则退出
        }
        // 失败则重试,直到成功
    }
}
该逻辑利用硬件级别的原子指令,保证在多线程环境下不会出现中间状态被破坏的问题。

适用场景与限制

虽然`atomic`包高效,但其使用受限于数据类型和操作复杂度。适合场景包括:
  1. 状态标志位切换
  2. 引用计数管理
  3. 简单计数器实现
操作类型函数示例用途说明
读取atomic.LoadInt32安全读取共享变量
写入atomic.StoreInt32安全设置新值
增减atomic.AddInt64用于计数场景
正确理解这些基础概念是掌握Go并发模型的关键一步。

第二章:CompareAndSwap原理解析与实战应用

2.1 CAS操作的核心机制与ABA问题剖析

CAS操作的基本原理
CAS(Compare-And-Swap)是一种无锁原子操作,用于实现多线程环境下的数据一致性。其核心逻辑是:仅当内存位置的当前值等于预期值时,才将该位置更新为新值。这一过程是原子的,避免了传统锁带来的性能开销。
func CompareAndSwap(addr *int32, old, new int32) bool {
    if *addr == old {
        *addr = new
        return true
    }
    return false
}
上述伪代码展示了CAS的逻辑流程。参数addr为内存地址,old为期望原值,new为目标写入值。只有在当前值与期望值一致时,写入才会生效。
ABA问题的产生与影响
尽管CAS能保证值的“相等”,但无法识别值是否曾被修改后又恢复。例如:线程T1读取值A,此时另一线程T2将其改为B再改回A,T1的CAS仍会成功。这种“ABA现象”可能导致逻辑错误,尤其在涉及资源生命周期管理时。
  • 典型场景:无锁栈或链表中节点重用
  • 根本原因:缺乏版本控制或时间戳机制
  • 解决方案:使用带标记的原子引用(如Java中的AtomicStampedReference)

2.2 使用CompareAndSwap实现无锁计数器

在高并发场景下,传统互斥锁可能带来性能瓶颈。无锁编程通过原子操作实现线程安全,其中 CompareAndSwap(CAS)是核心机制之一。
基本原理
CAS 操作包含三个操作数:内存位置 V、旧值 A 和新值 B。仅当 V 的当前值等于 A 时,才将 V 更新为 B,否则不执行任何操作。该过程是原子的。
Go语言实现示例
type Counter struct {
    val int64
}

func (c *Counter) Inc() {
    for {
        old := atomic.LoadInt64(&c.val)
        new := old + 1
        if atomic.CompareAndSwapInt64(&c.val, old, new) {
            break
        }
    }
}
上述代码通过 atomic.CompareAndSwapInt64 实现递增。若多个协程同时修改,失败者会重试,直到成功更新为止。
  • 优点:避免锁竞争,提升并发性能
  • 缺点:高争用下可能导致“ABA”问题或无限循环

2.3 并发场景下的CAS重试策略设计

在高并发环境下,基于CAS(Compare-And-Swap)的无锁操作常因竞争激烈导致失败率上升。为提升成功率与系统吞吐,合理的重试策略至关重要。
指数退避与随机化延迟
为避免线程持续高速自旋造成资源浪费,可采用指数退避机制,在每次重试时引入逐渐增长的延迟:
func casWithBackoff(retries int) bool {
    for i := 0; i < retries; i++ {
        if atomic.CompareAndSwapInt32(&value, expected, newValue) {
            return true
        }
        time.Sleep((1 << i) * time.Millisecond + 
                   time.Duration(rand.Intn(1000))*time.Microsecond)
    }
    return false
}
上述代码中,1 << i 实现指数增长,叠加随机微秒级抖动防止“重试风暴”,有效降低冲突频率。
重试策略对比
策略优点缺点
无退避响应快CPU占用高
固定间隔实现简单可能同步冲突
指数退避+随机化平衡性能与负载延迟略增

2.4 基于CAS的线程安全单例模式实现

在高并发场景下,传统的双重检查锁定(DCL)单例可能因指令重排序导致线程安全问题。基于CAS(Compare-And-Swap)操作的实现方式提供了一种无锁且高效的替代方案。
实现原理
利用原子变量和CAS操作确保实例创建的唯一性。线程在初始化对象时通过原子更新判断是否由自己完成实例化,避免重复构造。
public class CasSingleton {
    private static final AtomicReference<CasSingleton> INSTANCE = new AtomicReference<>();

    public static CasSingleton getInstance() {
        while (true) {
            CasSingleton current = INSTANCE.get();
            if (current != null) return current;
            CasSingleton newInstance = new CasSingleton();
            if (INSTANCE.compareAndSet(null, newInstance)) return newInstance;
        }
    }
}
上述代码中,`AtomicReference` 保证对实例引用的操作是原子的。`compareAndSet` 方法基于CAS机制,仅当当前值为 `null` 时才设置新实例,失败则循环重试。
优势对比
  • 避免使用 synchronized 关键字,减少线程阻塞
  • 无锁设计提升高并发下的性能表现
  • 逻辑清晰,易于维护和扩展

2.5 CompareAndSwap性能分析与适用场景

原子操作的核心机制
CompareAndSwap(CAS)是实现无锁并发控制的基础,依赖CPU提供的原子指令完成。它通过比较并交换内存值的方式避免使用互斥锁,减少线程阻塞。
func incrementWithCAS(counter *int32) {
    for {
        old := *counter
        new := old + 1
        if atomic.CompareAndSwapInt32(counter, old, new) {
            break
        }
    }
}
上述代码尝试通过CAS递增计数器。若期间有其他线程修改了counter值,则操作失败并重试,确保更新的原子性。
性能对比与适用场景
  • 高竞争环境下,频繁重试导致CPU占用上升
  • 低争用场景下,CAS显著优于传统锁机制
  • 适用于计数器、状态标志、无锁数据结构等轻量级同步需求
场景CAS性能锁性能
低争用高效一般
高争用下降明显相对稳定

第三章:Load与Store操作深入探讨

3.1 原子读写的内存顺序语义解析

在并发编程中,原子操作虽保证了读写不可分割,但编译器和处理器可能对指令重排,影响多线程逻辑一致性。为此,内存顺序(Memory Order)定义了原子操作周围的内存访问如何排序。
六种内存顺序模型
C++11 定义了六种内存顺序策略,其中最常用包括:
  • memory_order_relaxed:仅保证原子性,无同步或顺序约束;
  • memory_order_acquire:用于加载操作,确保此后所有读写不被重排至其前;
  • memory_order_release:用于存储操作,确保此前所有读写不被重排至其后;
  • memory_order_seq_cst:默认最强模式,提供顺序一致性保障。
代码示例与分析
std::atomic<bool> ready{false};
int data = 0;

// 线程1
void producer() {
    data = 42;                                    // 写共享数据
    ready.store(true, std::memory_order_release); // 释放操作,防止重排到前面
}

// 线程2
void consumer() {
    while (!ready.load(std::memory_order_acquire)) { // 获取操作,防止后续读写提前
        std::this_thread::yield();
    }
    assert(data == 42); // 永远不会触发
}
上述代码通过 acquire-release 语义建立同步关系:store 的 release 与 load 的 acquire 形成“synchronizes-with”关系,确保 data 的写入对 consumer 可见。

3.2 使用Load/Store构建线程安全配置管理

在高并发系统中,配置的动态更新必须保证线程安全。通过原子性的 Load 和 Store 操作,可以避免锁竞争,提升读取性能。
原子操作保障一致性
使用指针的原子读写替代传统互斥锁,能显著降低读操作开销。每次配置更新时,将新配置对象完整构造后,通过原子 Store 发布;读取时使用原子 Load 获取当前配置指针。
var config atomic.Value // *Config

func Set(cfg *Config) {
    config.Store(cfg)
}

func Get() *Config {
    return config.Load().(*Config)
}
上述代码中,atomic.Value 确保对配置指针的读写是原子的。Store 发布新配置前需完整初始化,防止中间状态暴露。Load 操作无锁,适合高频读场景。
适用场景对比
方案读性能写性能适用场景
Mutex低中读写均衡
Load/Store高高读多写少

3.3 LoadAcquire与StoreRelease的实践对比

内存序语义差异
LoadAcquire 保证后续读写操作不会重排到其之前,常用于获取共享资源;StoreRelease 确保之前的读写不会重排到其之后,适用于释放资源。二者协同实现同步。
代码示例对比

// 线程1:发布数据
data = 42;                                
std::atomic_thread_fence(std::memory_order_release);
flag.store(true, std::memory_order_relaxed);

// 线程2:获取数据
if (flag.load(std::memory_order_relaxed)) {
    std::atomic_thread_fence(std::memory_order_acquire);
    assert(data == 42); // 一定成立
}
上述代码中,memory_order_release 配合 acquire 构建同步关系。StoreRelease 防止前面的写被推后,LoadAcquire 阻止后面的读被提前,确保 data 的写入对另一线程可见。
  • LoadAcquire 常用于锁或信号量获取后读取共享状态
  • StoreRelease 适合在修改共享数据后通知其他线程

第四章:综合案例与高级技巧

4.1 实现一个无锁的并发队列

在高并发场景下,传统的互斥锁队列可能成为性能瓶颈。无锁队列通过原子操作实现线程安全,显著提升吞吐量。
核心设计原理
无锁队列通常基于CAS(Compare-And-Swap)操作维护头尾指针,允许多个线程同时入队和出队,避免阻塞。
Go语言实现示例
type Node struct {
    value int
    next  *atomic.Value // *Node
}

type Queue struct {
    head, tail *Node
}
每个节点的 next 指针使用 atomic.Value 包装,确保原子读写。head 指向哨兵节点,tail 指向最后一个实际节点。
入队操作流程
  • 创建新节点,并循环读取当前 tail
  • 使用 CAS 将 tail 的 next 指针指向新节点
  • 成功后,原子更新 tail 指针
该过程无需锁,依赖硬件级原子指令保证一致性。

4.2 原子指针在状态机中的应用

在高并发状态机实现中,状态的切换必须保证线程安全。原子指针(atomic pointer)提供了一种无锁(lock-free)的状态更新机制,适用于频繁读写状态的场景。
状态切换的原子性保障
通过原子指针操作,可避免使用互斥锁带来的性能开销。例如,在 Go 中使用 sync/atomic 包操作状态指针:
type State struct {
    Name string
}

var statePtr unsafe.Pointer // 指向当前状态

func UpdateState(newState *State) {
    atomic.StorePointer(&statePtr, unsafe.Pointer(newState))
}

func GetCurrentState() *State {
    return (*State)(atomic.LoadPointer(&statePtr))
}
上述代码中,StorePointer 和 LoadPointer 确保状态读写的一致性与可见性,无需加锁即可实现多协程安全访问。
应用场景优势对比
方案性能复杂度
互斥锁低中
原子指针高高

4.3 结合Channel与Atomic操作的混合模型

在高并发场景下,单纯依赖 Channel 或原子操作均存在局限。通过将两者结合,可构建高效且安全的混合同步模型。
协同机制设计
Channel 用于任务分发与协程通信,而 atomic 操作则处理轻量级状态更新,避免锁开销。
  • Channel 负责 goroutine 间消息传递
  • atomic 操作保障计数器、标志位等共享数据一致性
var counter int64
ch := make(chan int, 10)

go func() {
    for val := range ch {
        // 原子递增计数
        atomic.AddInt64(&counter, int64(val))
    }
}()
上述代码中,ch 传输增量值,atomic.AddInt64 确保多协程写入时无数据竞争。该模式适用于日志统计、指标采集等场景,兼具通信清晰性与性能优势。

4.4 常见误用模式与调试建议

并发访问未加锁导致数据竞争
在多协程环境中共享变量时,未使用互斥锁是常见错误。例如:

var counter int
for i := 0; i < 10; i++ {
    go func() {
        counter++ // 数据竞争
    }()
}
该代码中多个 goroutine 同时写入 counter,违反了内存可见性规则。应使用 sync.Mutex 保护临界区。
典型问题归纳
  • 忘记调用 Unlock() 导致死锁
  • 在 defer 中调用 Lock(),逻辑颠倒
  • 复制包含锁的结构体,破坏锁语义
调试建议
启用 Go 的竞态检测器:go run -race,可有效捕获运行时数据竞争,结合日志输出定位调用源头。

第五章:总结与原子操作的最佳实践

避免过度使用原子操作
原子操作虽高效,但并非所有并发场景都适用。在高争用环境下,频繁的 CAS(Compare-And-Swap)可能导致 CPU 资源浪费。应优先评估是否可通过锁分离或无锁数据结构优化。
合理选择原子类型
Go 提供了多种原子操作类型,如 int32、int64、Pointer 等。注意 int64 在 32 位系统上非原子,必须确保平台兼容性:

var counter int64

// 安全递增
atomic.AddInt64(&counter, 1)

// 读取值
current := atomic.LoadInt64(&counter)
结合内存屏障保障可见性
原子操作隐含内存屏障,可确保写操作对其他 goroutine 及时可见。以下场景中,无需额外同步原语:
  • 状态标志更新(如 ready 变量)
  • 引用计数管理
  • 轻量级配置热更新
实战案例:并发请求限流器
使用原子操作实现简单计数型限流器,避免锁开销:

type RateLimiter struct {
    current int64
    limit   int64
}

func (r *RateLimiter) Allow() bool {
    current := atomic.LoadInt64(&r.current)
    if current >= r.limit {
        return false
    }
    return atomic.AddInt64(&r.current, 1) <= r.limit
}
性能对比参考
操作类型平均延迟 (ns)适用场景
atomic.AddInt642.1高频计数
mutex.Lock25复杂临界区

Load → Compare → Swap → Retry on Fail

sync/atomic 基本使用 首先,我们来理解一下什么是原子操作,所谓原子操作就是指该操作是不可分割的,在执行完毕之前不会被其他的任务或者事件中断,该操作的内部不能被高层的操作发现并分割执行,处理器会首先保证我们这些操作内存的原子性,也就是说当向该内存地址写入或者读取数据的时候,其他的操作无法获取该内存的地址,也就是保证了该内存所保存数据的正确性。 在sync/atomic中提供了许多原子操作支持,主要有五大类: Load load 一类的方法接收一个地址,并返回该地址中的数据该类方法主要负责从相应的内存地址中获取对应的值 return 阅读详情

相关推荐

DIY便携式PEMF磁脉冲治疗仪:百元成本自制生物物理疗法设备

脉冲电磁场(PEMF)疗法是一种基于生物物理原理的非侵入性技术,它通过特定频率的电磁脉冲作用于细胞层面,影响细胞膜电位和离子通道活动,从而可能调节细胞代谢与功能。其技术价值在于提供了一种物理干预手段,在健康科技和生物黑客领域被探索用于放松、恢复等场景。实现PEMF的核心是通过信号发生与功率放大驱动电磁线圈产生可控磁场。本文以蓝牙音频模块和智能手机App为切入点,详细解析了如何利用低成本电子元件(如DFRobot XY-WRBT模块和漆包线线圈)构建一个可自定义频率的便携式PEMF设备,涵盖了从电路设计、线圈

weixin_31476015的博客 354

go atomic原子操作详细解读

修改完成后,缓存行为修改状态,其他核心的该缓存行为无效状态,此时若有核心读取该缓存行,就将缓存行写入内存,该核心上的缓存行状态更新为共享;atmoic包怎么用?以加法为例,变量加法运算操作并不是原子性的,包括从内存中取值放入加法寄存器、寄存器运算得到结果、将结果写回内存,在并发环境下,一个协程的运算结果可能被另一个覆盖,从而导致丢失修改的问题,例如以下代码的最后打印结果不会是10000。总的逻辑是,当一个核心读取内存中数据在自己的本地缓存中并且只有该核心的缓存拥有该缓存行,这个缓存行的状态为。

sunningzhzh的博客 2780

解决Cursor AI工具地域限制报错的方法与原理

地理围栏(GEO-fencing)是现代云服务常用的访问控制技术,通过IP地址库匹配、支付系统验证等方式实现区域限制。在AI编程工具领域,这种技术常导致类似Cursor出现的'unsupported country region'报错。从技术实现看,服务商会综合HTTP头信息、时区设置等多维度数据进行地理位置判断。开发者可通过调整网络出口、配置本地模型或使用企业版等方案解决。本文以Cursor为例,详细分析了AI工具地域限制的底层原理,并提供了包括Ollama本地部署在内的多种工程实践方案,特别适合需要稳定

weixin_30820077的博客 985

golang 互斥锁原理

互斥锁 1、互斥锁概念 对于同一份资源来说,为了保证 在多个线程或者协程同时访问的时候,保证数据的读取不会出现错误。 互斥锁相对于 读写锁而言更加绝对一些,互斥锁不论是读写,加过锁后,都是互斥的,需要等待 2、Mutex 数据结构 type Mutex struct { state int32 // 互斥锁状态 sema uint32 // 信号量 } sema 表示信号量,用来控制 goroutine 的 阻塞休眠和唤醒。协程阻塞时等待该信号量,协程解锁是释放该信号量并唤醒等待信号量的协

weixin_43753680的博客 1532

告别玄学调参:手把手教你用LSTM-AutoEncoder为传感器数据做异常检测(实战篇)

本文详细介绍了LSTM-AutoEncoder在传感器数据异常检测中的工程化实践,包括数据预处理、模型架构设计和生产环境部署策略。通过结合LSTM的时间序列处理能力和AutoEncoder的特征提取优势,该方法能够有效识别温湿度、PM2.5等传感器数据的异常模式,适用于工业物联网和室内空气质量监测等场景。

weixin_29212429的博客 477

SLAM算法的优缺点

SLAM(Simultaneous Localization and Mapping,同时定位与地图构建)算法是一种通过传感器数据实时估计机器人自身位置和构建环境地图的技术。

selenia8860的博客 2908

Go原子操作 sync/atomic

sync/atomic包提供了底层的原子级内存操作,其执行过程不能被中断,这也就保证了同一时刻一个线程的执行不会被其他线程中断,也保证了多线程下数据操作的一致性。 操作的数据类型共有六种:int32, int64, uint32, uint64, uintptr, unsafe.Pinter,每一种类型又提供了五种操作:Add增减, CompareAndSwap比较并交换, Swap交换, Load载入, Store存储。 函数名以"操作+类型"组合而来。例如AddInt32/AddUint64/LoadI

笔记 1063

“详规一张图”——上海土地利用数据

本文围绕城市规划与土地管理中空间数据的重要性,介绍了基于地理信息系统(GIS)技术对上海市用地数据进行获取与处理的具体方法。文章以上海市为例,详细阐述了如何通过构建以10米为间隔的网格点覆盖全市范围,并采用GET请求方式从“上海用地规划官网:详细规划‘一张图’公众版”平台获取地块信息的过程。通过对API接口参数的设置,包括坐标系、几何类型和返回格式等,实现了对每个网格点对应地块的属性信息(如规划用地类型、容积率、地块编号等)及几何形状信息的提取。

weixin_45812624的博客 2198

[go]原子操作atomic包简介

文章目录简介原子操作与互斥锁区别原子操作增加操作比较并交换操作载入操作atomic.Valuevalue读取value存储 原子操作就是不可中断的操作,这些操作对外表现成一个不可分割的整体,他们要么都执行,要么都不执行,外界是看不到原子操作的中间状态。 简介 go语言通过内置sync/atomic包提供对原子操作的支持,包括(以下XXType为:int32、int64、uint32、uint64、uintptr): 增减操作(AddXXType):保证对操作数的原子增减; 载入操作(LoadXXType)

飞鹰技术 3252

【图像超分】论文复现:CVPR 2024 | 轻量化超分 | 窗口注意力改进 | CAMixerSR的Pytorch源码复现,跑通源码,获得指标和超分结果,计算复杂度,架构梳理拆解,逐行注释!

本文介绍了超分辨率重建方法CAMixerSR的代码实现与运行指南。文章亮点包括:完整跑通源码获取PSNR/SSIM指标和可视化结果;详细解析模型架构与关键代码注释,帮助快速复现基线模型。实验部分提供了测试配置文件和训练设置说明,支持2K/4K/8K大图像超分和x2/x4轻量化超分。环境依赖PyTorch和BasicSR框架,数据集包含DIV2K等常用基准。测试结果与论文指标一致,可视化输出保存至指定目录。训练配置可自定义数据集路径、GPU数量等参数。该实现突出了CAMixerSR在降低W-MSA复杂度方面的

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 440

ESP32设备驱动-AS5600磁性旋转位置传感器

AS5600 是一款可编程的 12 位高分辨率非接触式磁性旋转位置传感器。 AS5600可以作为磁性电位器或磁性编码器使用,具有出色的可靠性和耐用性。 与传统电位器/编码器相比,AS5600具有显着优势:高精度、非接触式、旋转角度无限制。 所有这些优点使其适用于非接触式角度测量应用,例如机器人手臂、云台、电机闭环控制、机床轴定位。

视觉与物联智能 2553

Go语言中的Atomic:无锁编程的艺术

Atomic是Go语言中用于实现无锁编程的一个包,它提供了一组原子操作,可以在不使用互斥锁的情况下安全地操作共享变量。通过理解Atomic的原理和最佳实践,我们可以编写更加高效、可靠的并发程序。选择合适的原子操作:根据具体场景选择Add、Load、Store、Swap或CompareAndSwap避免过度使用原子操作:对于复杂的数据结构,使用互斥锁更合适注意内存顺序:原子操作保证操作的原子性,但不保证内存顺序性能优化:原子操作比互斥锁更快,但仍有开销,避免在热点路径中频繁使用。

好代码自己会说话,烂代码才需要注释来圆谎 4599

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Uber Go Style Guide 解读:用 go.uber.org/atomic 替代裸类型原子操作

`sync/atomic` 虽然功能强大,但它要求开发者手动在"原始类型"与"原子操作"之间建立对应关系,极易在读写时忘记调用原子函数而埋下数据竞争(data race)。本篇文章基于 Uber Go Style Guide 的 [Use go.uber.org/atomic](https://link.gitcode.com/i/d293b08b62af724fee83cd3d9524301c)

gitblog_00912的博客 1041

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

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

sync/atomic 原子操作使用与解析

前言 Go 源码版本:1.16 1. 引入 下面这段程序输出是多少呢? package main import ( "fmt" "time" ) var a int = 0 func main() { for i := 0; i < 1000; i++ { go func() { a++ }() } fmt.Printf("a = %d\n", a) time.Sleep(time.Second) }

zwjason1999 的博客 745

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

语言中conio是什么库_go语言标准库sync/atomic中的原子操作

引言在goroutine中访问外部的变量并不安全,我们先看看下面这个例子,我们执行一次计数,使用sync.WaitGroup包保证我们创建的1000个goroutine全部执行完毕后再输出n,运行程序看看结果如何:package main import ( "fmt" "sync" "sync/atomic" ) func main() { var n int3...

weixin_33754535的博客 215

KubeSphere 仓库中的 go.uber.org/atomic:Go 原子类型安全封装库完整指南

`go.uber.org/atomic` 是 Uber 开源的原子操作封装库,它在标准库 `sync/atomic` 的基础上,将原始类型包装为类型安全的原子对象,提供 `Load/Store/Add/Sub/CompareAndSwap` 等更易用、更不易出错的 API。本指南以 KubeSphere 仓库中随附的 [vendor/go.uber.org/atomic/README.md](ht

gitblog_00109的博客 770

深入理解Go语言中的并发编程【29】【原子操作(atomic包)、并发安全性】

深入理解Go语言中的并发编程【29】【原子操作(atomic包)、并发安全性】

m0_52896752的博客 390

详解并发编程基础之原子操作(atomic包)

前言嗨,大家好,我是asong。最近想写一个并发编程系列的文章,使用Go也有一段时间了,但是对并发的理解不是很透彻,借着这次总结,希望能更进一步。我们以"原子操作"开篇,...

qq_39397165的博客 960

go.uber.org/atomic 深度解析:原子类型安全封装的原理与 OpenShift origin 仓库中的实践

go.uber.org/atomic 是一个为 Go 基本类型提供原子访问封装的轻量级库,它在标准库 `sync/atomic` 之上构建了一套更安全、更便捷的类型化 API。本文以 OpenShift origin 仓库中 vendored 的 [vendor/go.uber.org/atomic](https://link.gitcode.com/i/acccfcf86b68127807faf

gitblog_01056的博客 505

Grafana Mimir 中的 go.uber.org/atomic:原子类型包装器库的源码级深度解析

> 本文以仓库 `vendor/go.uber.org/atomic` 中随 Grafana Mimir 一同引入并实际投入生产的第三方库文档([vendor/go.uber.org/atomic/README.md](https://link.gitcode.com/i/320302a2a6cb1947df70e36625d8968d))为核心,系统讲解该库在标准库 `sync/atomic`

gitblog_00776的博客 902

Go语言自学系列 | golang并发编程之原子操作详解

视频来源:B站《golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]》 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,请移步至知乎网站,谢谢支持! 附上汇总贴:Go语言自学系列 | 汇总 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/484035621 atomic提供的原子操作能够确保任一时刻只有一个goroutine对变量进行操作,善用atomic能够避免程序中出现大量的锁操作。 atomic常见.

团爸讲算法 1357

OpenShift 仓库中的 go.uber.org/atomic 演进全解:从 v1.0.0 到 v1.11.0 的类型体系、API 变更与源码实现

本篇技术指南以当前仓库 vendor 目录下 `go.uber.org/atomic`(版本 v1.11.0)的 CHANGELOG 为核心骨架,结合其完整源码,系统讲解该库从 2016 年 v1.0.0 到 2023 年 v1.11.0 的演进脉络:所有原子类型(整数、浮点、字符串、错误、时间、指针等)的引入时机、核心 API 语义、序列化能力与安全防护设计。读完本文,你将能理解该库相比标准库

gitblog_00514的博客 425

Go 并发编程利器:go.uber.org/atomic 原子类型包装库源码级实战指南

在 Go 服务端开发中,多 goroutine 共享变量的原子访问是最容易出错、又最常被忽视的环节:标准库 `sync/atomic` 功能强大,但要求开发者牢记哪些变量必须走原子操作,一旦用普通赋值或比较,就会埋下数据竞争(data race)隐患。`go.uber.org/atomic` 以"类型安全包装"的方式把这个问题从"人肉记忆"变成"编译器强制"——它完整保留标准库原子语义,却把 `i

gitblog_00187的博客 337

go.uber.org/atomic 原子类型演进全解:从 v1.0 到 v1.11 的 API 变迁与源码实现

`go.uber.org/atomic` 是 Uber 开源的 Go 原子操作封装库,它在标准库 `sync/atomic` 的基础上,为 `int`、`bool`、`float`、`string`、`time.Duration`、`error` 乃至任意类型的指针提供了**类型安全的原子读写封装**,帮助开发者避免"忘记哪个变量需要原子访问"的常见失误。本篇文章以该库的 [CHANGELOG.m

gitblog_00498的博客 357

go.uber.org/atomic 演进全解析:从 v1.0.0 到 v1.10.0 的类型体系与并发安全实践

go.uber.org/atomic 是 Uber 开源的 Go 原子类型封装库,它把标准库 `sync/atomic` 的底层原语包装成类型安全、开箱即用的原子类型,广泛用于需要无锁并发共享状态的 Go 服务中。本文以本仓库 vendor 目录下该库的 [CHANGELOG.md](https://link.gitcode.com/i/05cabd3d7fde1ab088aec3c3ad8c8d

gitblog_00568的博客 470
上一篇: 从旁观到核心贡献者:Go开源社区晋升路线图(仅限前1%掌握)
下一篇: Go内存分配性能调优:如何将GC停顿降低90%?
simcode
博客等级 码龄14年 154粉丝 2026原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值