XB_block(2)

Text Diffusion-202503-Block Diffusion03:训练中的前向、反向传播详细解释【训练阶段每一个block都知道当前block前的其他所有前置block的真值】 这段话本质上是在说:Block Diffusion 把序列分成多个 block;训练第bbb个 block 时,用“前面真实干净 block 作为条件 + 当前 block 的 noisy 版本作为输入”,通过一个带 block-causal mask 的共享 Transformer 来预测当前 block 的干净内容;并且通过输出/复用 KV cache,避免重复计算前缀,从而高效地并行计算所有 block 的去噪损失。 阅读详情

1.block的copy

在ARC环境下,编译器会在以下情况下自动将栈上的block复制到堆上

  • block作为函数的返回值
typedef void (^MJBlock)(void);
MJBlock myblock(int age)
{
    return ^{
        NSLog(@"---------%d",age);
    };
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
       
        int age = 10;
        NSLog(@"%@", [myblock(age) class]);
    }
    return 0;
}

//打印:__NSMallocBlock__
//当然,如果myblock没有捕获age的话,打印__NSGlobalBlock__
  • 将block赋值给__strong指针

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int age = 10;
        typedef void (^MJBlock)(void);
        MJBlock block = ^{
            NSLog(@"---------%d", age);
        };
        
        NSLog(@"赋值给__strong指针:%@", [block class]);
        
       NSLog(@"未赋值给__strong指针:%@", [^{
            
        } class]);
  }
  return 0;
}

打印:赋值给__strong指针:__NSMallocBlock__
     未赋值给__strong指针:__NSGlobalBlock__
  • block作为Cocoa API中方法名含有usingBlock的方法参数时

比如数组遍历 

   [arr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
    }];
  • block作为GCD API的方法参数时
 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"-------");
        });

此时的打印操作已经是属于堆上的block。

如果MRC环境下需要手动调用copy函数才能将block从栈复制到堆上

如

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int age = 10;
        typedef void (^MJBlock)(void);
        MJBlock block = [^{
            NSLog(@"---------%d", age);
        } copy];
        
        NSLog(@"赋值给__strong指针:%@", [block class]);
        
       NSLog(@"未赋值给__strong指针:%@", [^{
            
        } class]);
  }
  return 0;
}

当然也需要对应的release操作 

 

2.对象类型的auto变量

  • 如果在栈上的block内部访问了对象类型的auto变量时,不会对auto变量产生强引用

   

{


 Person *p = [[Person alloc] init];
    ^{
        NSLog(@"-------%@",p);
    }();

}
NSLog(@"===================");
打印:
-------<Person: 0x6000028143f0>

Person - dealloc

===================

可以看到栈上的block正常捕获对象类型auto变量,但是Person会在作用域结束后打印@"=============="前销毁

  • 如果是堆上的block内部访问了对象类型的auto变量时,会对auto变量产生强引用
   typedef void(^Myblock)(void);
    Myblock block;
    {
        
        Person* p = [[Person alloc] init];
        block = ^{
               NSLog(@"-------%@",p);
        };
        block();
    }
    NSLog(@"=======");

打印:
-------<Person: 0x6000027fc2f0>

=======

MJPerson - dealloc

没有在作用域结束之后立即释放。

原理:

1.如果block被拷贝到堆上,会调用block内部的copy(__main_block_copy_)函数,copy函数会调用_Block_object_assign函数,

_Block_object_assign函数会根据auto变量的修饰符(__strong、__weak、__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用。

2.如果block从堆上移除,会调用block内部的dispose(__main_block_dispose_)函数, dispose函数内部会调用_Block_object_dispose函数 _Block_object_dispose函数会自动释放引用的auto变量(release)

注意:copy函数与dispose函数都是在_main_block_desc_结构体中,当捕获了对象类型的auto变量,无论weak还是strong都会出现这两个函数,添加在size_t   reserved  和  size_t  Block_size后边

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
  void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};

3.__block修饰符底层

  • __block可以用于解决block内部无法修改auto变量值得问题
  • __block无法修饰全局变量和静态变量(static)

底层原理是:编译器会将__block变量包装成一个对象

int main(int argc, const char * argv[]) {
    @autoreleasepool {
      __block int age = 10;
      ^{
        age = 30;
        NSLog(@"age is %d", age);
       }();
   }
return 0;
}


//这段代码的底层结构(包括main函数)
int main(int argc, const char * argv[]) {
    

//包装外面的age变量
        __attribute__((__blocks__(byref))) __Block_byref_age_0 age = {(void*)0,(__Block_byref_age_0 *)&age, 0, sizeof(__Block_byref_age_0), 10};
        
//捕获包装过的age变量
        MJBlock block = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, p, (__Block_byref_age_0 *)&age, 570425344));

        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
   

    }

//block底层结构体实现
struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;

  __Block_byref_age_0 *age; // by ref

  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, NSObject *_p, __Block_byref_age_0 *_age, int flags=0) : p(_p), age(_age->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

//__Block_byref_age_0结构体的底层结构
struct __Block_byref_age_0 {
  void *__isa;
__Block_byref_age_0 *__forwarding;
 int __flags;
 int __size;
 int age;
};

可以看到先把即将要捕获的 __block修饰过的age变量包装成一个对象struct  __Block_byref_age_0,然后将这个对象捕获到block中,struct __main_block_impl_0中的age变量已经不是未修饰过的时候的 int age类型,而是__Block_byref_age_0 *age类型,也证实确实是捕获的一个对象类型的变量。

变量值的更改:

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref_age_0 *age = __cself->age; // bound by ref
           (age->__forwarding->age) = 20;
            
        }

通过包装过的对象中的forwarding指针修改age(forwarfing指针其实就是指向这个对象自己)。

注意:如果我们在block后边打印age的地址,那么这个age是__Block_byref_age_0的地址呢,还是__Block_byref_age_0结构体里的int age地址呢?

typedef void (^MyBlock) (void);

struct __Block_byref_age_0 {
    void *__isa;
    struct __Block_byref_age_0 *__forwarding;
    int __flags;
    int __size;
    int age;
};

struct __main_block_desc_0 {
    size_t reserved;
    size_t Block_size;
    void (*copy)(void);
    void (*dispose)(void);
};

struct __block_impl {
    void *isa;
    int Flags;
    int Reserved;
    void *FuncPtr;
};

struct __main_block_impl_0 {
    struct __block_impl impl;
    struct __main_block_desc_0* Desc;
    struct __Block_byref_age_0 *age;
};

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        __block int age = 10;
        
        MyBlock block = ^{
            age = 20;
            NSLog(@"age is %d", age);
        };
        
//将block转换成结构体
        struct __main_block_impl_0 *blockImpl = (__bridge struct __main_block_impl_0 *)block;
        
        NSLog(@"%p---%p", &age,blockImpl->age);
    }
    return 0;
}

用命令行p/x blockImpl-->age和 p/x &(blockImpl-->age-->age)分别打印age结构体和结构体里的int age地址,发现与结构体中的int age地址相等。

4.__weak

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    MJPerson *p = [[MJPerson alloc] init];
    
    __weak Person *weakP = p;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"1-------%@", weakP);
      
    });
    

    NSLog(@"touchesBegan:withEvent:");
}

打印结果:
2019-12-09 12:34:51.821036+0800 Interview03-测试[6028:400633] touchesBegan:withEvent:
2019-12-09 12:34:51.821209+0800 Interview03-测试[6028:400633] Person - dealloc
2019-12-09 12:34:52.918856+0800 Interview03-测试[6028:400633] 1-------(null)

由于Person是weak修饰的,打印时已经释放了 

 

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    Person *p = [[Person alloc] init];
    
    __weak Person *weakP = p;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"1-------%@", weakP);
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"2-------%@", p);
        });
    });
    
   
    NSLog(@"touchesBegan:withEvent:");
}

打印结果:
2019-12-09 12:32:49.854488+0800 Interview03-测试[5975:392337] touchesBegan:withEvent:
2019-12-09 12:32:50.854661+0800 Interview03-测试[5975:392337] 1-------<Person: 0x600001793a40>
2019-12-09 12:32:52.855110+0800 Interview03-测试[5975:392337] 2-------<Person: 0x600001793a40>
2019-12-09 12:32:52.855286+0800 Interview03-测试[5975:392337] Person - dealloc

会发现Person在3秒后才释放。

STM32F103x8/STM32F103xB performance line block diagram 本文详细解析了STM32F103xx系列芯片的系统框图架构。采用分层解析方式,从核心处理单元(Cortex-M3内核+调试模块)开始,依次剖析总线矩阵(支持多主机并行访问的AHB/APB分层架构)、存储系统(Flash+SRAM)、DMA控制器(7通道硬件数据搬运),以及丰富的外设资源(GPIO/定时器/通信接口/ADC等)。特别说明了电源管理系统(2.0-3.6V宽电压供电+备份域)和时钟管理单元(PLL倍频+外设时钟分配)的设计原理,完整呈现了该MCU从计算核心到功能接口的协同工作机制。 阅读详情

相关推荐

[LVGL] 刷新率优化

实验硬件:STM32F407ZGT6;2.4寸TFT-LCD模块(ILI9341驱动芯片、XTP2046触摸芯片)本文目标:lvgl的刷新率优化,解决拉帘子问题注意:本文在LVGL显示触摸代码移植完成的基础上进行,第一次使用lvgl可根据前文一步步移植,点击下方传送门查看相关文章传送门:STM32F4驱动ILI9341的TFT-LCD触摸屏(HAL库)(一)STM32F4驱动ILI9341的TFT-LCD触摸屏(HAL库)(二)[LVGL] 显示代码移植 基于STM32F4。

2301_77117901的博客 2784

MJiOS底层笔记--Block

本文属笔记性质,主要针对自己理解不太透彻的地方进行记录。 推荐系统直接学习小码哥iOS底层原理班---MJ老师的课确实不错,强推一波。 基本认识 block实际上为一个代码块 只有在末尾执行()才会调用 ^{ NSLog(@"this is a block!"); NSLog(@"this is a block!"); NSLog(@"this is a block...

weixin_34392843的博客 629

保姆级教程:在RK3588开发板上编译带MPP硬件加速的FFmpeg(含完整依赖库配置)

本文提供在RK3588开发板上编译支持MPP硬件加速的FFmpeg的详细教程,涵盖交叉编译环境搭建、MPP框架及依赖库配置,最终实现4K视频硬件编解码性能优化。通过实战步骤和性能对比,展示如何充分发挥RK3588的硬件加速能力。

weixin_30839881的博客 418

探究Block原理(上篇)-Block本质及存储域问题

主要内容: 1.理解Block的本质 2.理解Block的存储域分类 3.理解Block的Copy原理 一、探究Block的本质 从一个最简单的Block使用示例说起,我们分析如下代码: //main.m文件: #import <Foundation/Foundation.h> int main(int argc, char * argv[]) { int num = 10; ...

梧雨北辰的博客 593

C++上机——2023年“信息与未来”小学生编程思维展示官方题解

本次活动前三题是“根据问题描述实现代码”类型的问题,题解和示例代码由人工智能GPT-4直接阅读题面后生成――只要熟悉C++的语法和基本的编程、调试,即可解决p1、p2、p3。后三题有一定的算法性,我们给出命题思路和一些可能的解法。注意:本题解是面向指导教师的;指导教师在讲解时可以根据学生掌握程度进行调整。

qq_39127687的博客 2297

【微信小程序开发与设计】垃圾智能分类小程序

垃圾分类是将来生活可持续发展的必需项。但是很多人由于缺乏垃圾分类知识,或是因为垃圾分类困难,费时费力,所以没有好好贯彻垃圾分类政策,此时设计一款方便于群众进行智能化垃圾识别分类的微信小程序就显得尤为必要。

Markelle_Fultz的博客 8246

NSLog

应该说NSLog打印信息是初学者最喜欢的调试手法,也是最简单的调试,通过打印出的信息查看程序运行的路径。但是打印出的信息较少,本身NSLog效率较低,有人使用宏做了部分优化,代码如下:能够打印出所在类名、所在方法名、详细时间、行号。 1 2 3 4 5 6 7 8 9 10 11 12 13

FIGHTING的专栏 1008

从零开始理解异构算力调度:全国一体化算力算网平台实战解析

本文深入解析了异构算力调度技术在全国一体化算力算网平台中的实战应用。通过资源抽象层设计、动态感知引擎和跨云调度算法,实现AI训练任务的高效资源分配,显著提升计算效率并降低成本。特别针对GPU等异构算力的智能调度方案,为多云协同环境下的AI开发提供实用指南。

weixin_28730927的博客 334

C++编程思想-引用和拷贝构造函数+对象创建动态+继承和组合+多态性和虚函数

C++中的引用 像常量型指针。 (const在*右边使指针本身成为const) 要求: 1.必须初始化 2.只能指向一个对象 3.没有null引用 参数传递规则: 传值方式需要调用ctr and dtr,然而如果不想改变参数,则可以通过常量引用传递,它仅需要将地址压栈。 拷贝构造函数 X(X&) 1.按值传递和返回 1). 传递和返回大对象 2). 函数调用栈的框架 函数参数 返回地址 局部变量 3). 重入意味着任何函数可以中断..

千里行 263

关于42步进电机驱动——基于STM32 HAL库实现

我找了好多资料,好多关于42步进电机的都是文档,这么文档都需要积分,需要积分就算了内容还非常差,浪费时间和电脑的内存。关于大部分是基于Arduino和51去驱动的 42步进电机驱动硬件如下: 首先你要了解步进电机的驱动原理,我也不啰嗦了,请看这边博客: 二相四线,四相五线,四相六线步进电机接线及驱动方法 , 看完这篇你就知道驱动和接线的原理了。 起初我也为如何接线烦恼,因为有些博客在讲述这些问题的时候没有讲的很透彻。 方法如下: ①用万用表调到欧姆档,用其中一个表笔搭在一个引脚上,依次测其它.

Jodan132的博客 1万+

OpenTK简介

OpenTK 因其强大的功能、跨平台特性和灵活性,适用于多种需要图形和计算能力的应用场景,为开发者提供了丰富的可能性和创作空间。

仰望星空的博客 1980

Objective-C中的alloc和init问题

从开始学的NSString *name=[[NSString alloc] init] 起,仅仅这句话是分配内存空间,一直在用,从来没考虑过它的内部是怎么实现的。今天无意中看到了这一句代码: NSString *name = [NSString alloc]; NSLog(@"%p",name); name = [name init]; NSLog(@"%p",name); 试着...

weixin_30532759的博客 147

YOLO系列算法改进 | Neck改进篇 | 融合FAAFusion傅里叶角度对齐模块 | 攻克多尺度方向特征冲突,角度检测精度飙升! | CVPR 2026

YOLO系列算法改进 | Neck改进篇 | 融合FAAFusion傅里叶角度对齐模块 | 攻克多尺度方向特征冲突,角度检测精度飙升! | CVPR 2026 (以YOLO26最新目标检测模型为基础,利用FAAFusion傅里叶角度对齐模块改进Neck部分)

2502_91881744的博客 317

XB_block(3)

1.__block的内存管理 我们已经知道,__block修饰符会把auto变量包装成一个对象 1.当block在栈上时,并不会对__block变量产生强引用 2.当block被copy到堆时,会调用block内部的copy函数,copy函数内部会调用_Block_object_assign函数, _Block_object_assign函数会对__block变量形成强引用(retain),...

HuberCui的博客 351

jre9下载 jdk9

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

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

XB_block(1)

1.block的本质 block本质上是一个OC对象,内部封装了函数调用和函数调用环境,底层结构如下图,第一位是__block_impl,第二位是__main_block_desc_0,后边是捕获的变量。 其中__block_impl中存有一个FuncPtr的函数指针,block通过该指针调用了内部的函数。 注意:当调用函数的时候理论上应该是block-->impl.FuncPtr这样...

HuberCui的博客 387

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

[黑马IOS自学第十七篇]OC BLOCK学习

block概念和基本使用 SEL id BLOCK BOOL Boolean 衍生的数据类型 基本概念       定义个变量去存储代码块         函数名就是地址无需加&取地址符         #import   int main(intargc, const char* argv[]) {     @autore

wadeAD的博客 835

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

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

防止Block 循环引用,__weak、__block、__strong的使用

循环引用的理解 首先说一下循环引用,为什么没用 __weak 修饰就直接用 self. 属性,有时候不会造成循环引用,有时候会造成循环引用呢。 循环引用是指两个或者多个对象循环持有造成的无法释放(即引用计数减不到0)。 例如:类 Person 有个属性 block, 在 block 实现后, 此时 self 持有 block,如果在 block 中,直接使用 self,block 将持有 sel...

11月的淡然的博客 680

ik_llama.cpp 中 IQ2_K Metal 内核修复与优化实战解析:block scales 布局变更引发的回归修复

本文以 ik_llama.cpp 仓库中的 PR #86(《Fix and optimize iq2k Metal implementation》)为主线,深入剖析一次典型的量化格式演进与后端内核同步问题:上游 PR 修改了 `IQ2_K` 量化块的 scales(缩放因子)布局,却遗漏了对应的 Metal 点积内核,导致 Apple Silicon 上矩阵乘法结果错误。文章将结合仓库源码,完整还

gitblog_00688的博客 404

CANN/cannbot-skills:Block Pointer迁移注意事项

`tl.make_block_ptr` 是 Triton 中用于描述结构化内存访问的高级抽象,在 GPU 和 NPU 上的行为存在显著差异。NPU 对 Block Pointer 的 stride、order 参数有严格限制,转置语义只能通过 order 参数表达,且与复杂循环/分支语句搭配时可能出现编译问题。本文详细说明 Block Pointer 在 NPU 上的行为差异、限制和替代方案。

gitblog_00660的博客 399

ImageConverter引起的 invalid address or address of corrupt block 0xb7feab58 passed to dlfree

虹软人脸识别,其方法要传NV21格式的byte[], github上有一个虹软的Demo,是不是虹软工作人员写的不清楚,这个Demo里bitmap转NV21格式byte[]用的是一个第三方库https://github.com/gqjjqg/android-extend, 用法如下: ImageConverter convert = new ImageConverter(); conver...

weixin_30911451的博客 162

【AD5933】如何实现AD5933 Block Read

如何利用STM32 HAL库的HAL_I2C_Mem_Read实现AD5933 Block Read功能

weixin_43676546的博客 776

golang pprof监控系列(2) —— memory,block,mutex 使用

经过上述的讲解,应该是能够明白相关的指标究竟是采集了哪些内容并且何时采集的了,而go tool pprof 工具的使用不是此文的重点,所以我直接省略掉了,也是没想到即使省略了,还是内容有那么多,那就把这部分的统计原理留到下一篇文章了,下一篇,memory,block,mutex 统计的原理介绍。

我活在当下,我巨他妈勇敢。 653

block 解析 - 局部变量

局部变量 block内使用局部变量,一般都是截获变量(只读),截获离block初始化最近的一次的值。 引用官方文档: Stack (non-static) variables local to the enclosing lexical scope are captured asconst variables.Their values are taken at the point ...

weixin_30532837的博客 180

linux java block,Linux 内核的一个问题

是virtio 驱动,但是没有启动[ 1.047924] md: ... autorun DONE.[ 1.050424] VFS: Cannot open root device "vda" or unknown-block(0,0): error -6[ 1.053462] Please append a correct "root=" boot option; here a...

weixin_39789979的博客 127
上一篇: XB_block(1)
下一篇: XB_block(3)
史蒂芬-周
博客等级 码龄9年 5粉丝 50原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值