runtime

本文转自:http://www.cocoachina.com/ios/20141018/9960.html

 

最近在找工作,Objective-C中的Runtime是经常被问到的一个问题,几乎是面试大公司必问的一个问题。当然还有一些其他问题也几乎必问,例 如:RunLoop,Block,内存管理等。其他的问题如果有机会我会在其他文章中介绍。本篇文章主要介绍RunTime。

RunTime简称运行时。就是系统在运行的时候的一些机制,其中最主要的是消息机制。对于C语言,函数的调用在编译的时候会决定调用哪个函数( C语言的函数调用请看这里 )。编译完成之后直接顺序执行,无任何二义性。OC的函数调用成为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(事实证明,在编 译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错。而C语言在编译阶段就会报错)。只有在真正运行的时候才会根据函数的名称找 到对应的函数来调用。

那OC是怎么实现动态调用的呢?下面我们来看看OC通过发送消息来达到动态调用的秘密。假如在OC中写了这样的一个代码:

1
[obj makeText];

其中obj是一个对象,makeText是一个函数名称。对于这样一个简单的调用。在编译时RunTime会将上述代码转化成

1
objc_msgSend(obj,@selector(makeText));

首先我们来看看obj这个对象,iOS中的obj都继承于NSObject。

1
2
3
@interface NSObject <nsobject> {
     Class isa  OBJC_ISA_AVAILABILITY;
}</nsobject>

在NSObjcet中存在一个Class的isa指针。然后我们看看Class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef struct objc_class *Class;
struct objc_class {
   Class isa;  // 指向metaclass
   
   Class super_class ;  // 指向其父类
   const char *name ;  // 类名
   long version ;  // 类的版本信息,初始化默认为0,可以通过runtime函数class_setVersion和class_getVersion进行修改、读取
   long info;  // 一些标识信息,如CLS_CLASS (0x1L) 表示该类为普通 class ,其中包含对象方法和成员变量;CLS_META (0x2L) 表示该类为 metaclass,其中包含类方法;
   long instance_size ;  // 该类的实例变量大小(包括从父类继承下来的实例变量);
   struct objc_ivar_list *ivars;  // 用于存储每个成员变量的地址
   struct objc_method_list **methodLists ;  // 与 info 的一些标志位有关,如CLS_CLASS (0x1L),则存储对象方法,如CLS_META (0x2L),则存储类方法;
   struct objc_cache *cache;  // 指向最近使用的方法的指针,用于提升效率;
   struct objc_protocol_list *protocols;  // 存储该类遵守的协议
     }

 

我们可以看到,对于一个Class类中,存在很多东西,下面我来一一解释一下:

Class isa:指向metaclass,也就是静态的Class。一般一个Obj对象中的isa会指向普通的Class,这个Class中存储普通成员变量和对 象方法(“-”开头的方法),普通Class中的isa指针指向静态Class,静态Class中存储static类型成员变量和类方法(“+”开头的方 法)。

Class super_class:指向父类,如果这个类是根类,则为NULL。

下面一张图片很好的描述了类和对象的继承关系:

iuqQFnm.png

注意:所有metaclass中isa指针都指向跟metaclass。而跟metaclass则指向自身。Root metaclass是通过继承Root class产生的。与root class结构体成员一致,也就是前面提到的结构。不同的是Root metaclass的isa指针指向自身。

Class类中其他的成员这里就先不做过多解释了,下面我们来看看:

@selector (makeText):这是一个SEL方法选择器。SEL其主要作用是快速的通过方法名字(makeText)查找到对应方法的函数指针,然后调用其函 数。SEL其本身是一个Int类型的一个地址,地址中存放着方法的名字。对于一个类中。每一个方法对应着一个SEL。所以iOS类中不能存在2个名称相同 的方法,即使参数类型不同,因为SEL是根据方法名字生成的,相同的方法名称只能对应一个SEL。

下面我们就来看看具体消息发送之后是怎么来动态查找对应的方法的。

首先,编译器将代码[obj makeText];转化为objc_msgSend(obj, @selector (makeText));,在objc_msgSend函数中。首先通过obj的isa指针找到obj对应的class。在Class中先去cache中 通过SEL查找对应函数method(猜测cache中method列表是以SEL为key通过hash表来存储的,这样能提高函数查找速度),若 cache中未找到。再去methodList中查找,若methodlist中未找到,则取superClass中查找。若能找到,则将method加 入到cache中,以方便下次查找,并通过method中的函数指针跳转到对应的函数中去执行。

 
 

转载于:https://www.cnblogs.com/muzijun/p/5762011.html

### 安装方法 ONNX Runtime 的安装可以通过 Python 的包管理工具 `pip` 进行。用户可以直接使用以下命令来安装最新版本的 ONNX Runtime: ```bash pip install onnxruntime ``` 如果需要特定版本的 ONNX Runtime,例如版本 1.16.0,则可以使用以下命令指定版本号进行安装: ```bash pip install onnxruntime==1.16.0 ``` 对于某些高级用例或开发需求,可能还需要从源码构建 ONNX Runtime,但这通常适用于有特殊定制需求的开发者[^1]。 ### 使用指南 安装完成后,可以通过 Python 导入 `onnxruntime` 模块来加载并运行 ONNX 模型。以下是一个简单的示例,展示如何使用 ONNX Runtime 加载模型并执行推理: ```python import onnxruntime as ort import numpy as np # 加载模型 session = ort.InferenceSession("path_to_model.onnx") # 准备输入数据 input_name = session.get_inputs()[0].name input_data = np.random.rand(1, 3, 224, 224).astype(np.float32) # 执行推理 outputs = session.run(None, {input_name: input_data}) # 输出结果 print(outputs) ``` 为了确保安装的 ONNX Runtime 性能满足预期,可以运行一些基准测试。这些测试将帮助了解模型在特定硬件上的性能。可以使用 ONNX 模型测试基准工具,或使用自定义脚本来测量推理时间和其他性能指标。例如,使用内置的基准工具: ```bash python3 -m onnxruntime.tools.benchmark --input path_to_model.onnx --input_feed input_name(input_data) --iter 10 ``` 这个命令会执行 10 次推理迭代,并报告平均推理时间等性能指标[^1]。 ### 调试技巧 ONNX Runtime 提供了强大的日志系统,这对于调试模型推理过程中的问题非常有用。通过合理配置日志级别和输出方式,开发者可以更高效地诊断模型推理过程中的各种问题。可以通过设置环境变量来控制日志级别,例如: ```bash ORT_LOG_LEVEL=VERBOSE ``` 此外,还可以通过编程方式配置日志记录器,以便于捕获和分析运行时的日志信息。这有助于快速定位和解决潜在的问题[^2]。 当遇到模型兼容性问题时,比如导出模型时报错 `Unsupported: ATen operator triu`,一种解决方案是替换为等效的 ONNX 算子。具体做法如下: ```python # 修改前 torch.triu(...) # 修改后 torch.onnx.symbolic_opset9.triu = lambda g, input: g.op("Trilu", input, upper=1) ``` 这种修改允许用户在导出模型时绕过 PyTorch 中不支持的操作,从而实现与 ONNX 的兼容[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值