当前位置: 首页 > 编程日记 > 正文

CFRunLoopRef 的内部逻辑(向 ibireme学习)

据苹果在文档里的说明,RunLoop 内部的逻辑大致如下:

/// 用DefaultMode启动
void CFRunLoopRun(void) {CFRunLoopRunSpecific(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 1.0e10, false);
}/// 用指定的Mode启动,允许设置RunLoop超时时间
int CFRunLoopRunInMode(CFStringRef modeName, CFTimeInterval seconds, Boolean stopAfterHandle) {return CFRunLoopRunSpecific(CFRunLoopGetCurrent(), modeName, seconds, returnAfterSourceHandled);
}/// RunLoop的实现
int CFRunLoopRunSpecific(runloop, modeName, seconds, stopAfterHandle) {/// 首先根据modeName找到对应modeCFRunLoopModeRef currentMode = __CFRunLoopFindMode(runloop, modeName, false);/// 如果mode里没有source/timer/observer, 直接返回。if (__CFRunLoopModeIsEmpty(currentMode)) return;/// 1. 通知 Observers: RunLoop 即将进入 loop。__CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopEntry);/// 内部函数,进入loop__CFRunLoopRun(runloop, currentMode, seconds, returnAfterSourceHandled) {Boolean sourceHandledThisLoop = NO;int retVal = 0;do {/// 2. 通知 Observers: RunLoop 即将触发 Timer 回调。__CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeTimers);/// 3. 通知 Observers: RunLoop 即将触发 Source0 (非port) 回调。__CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeSources);/// 执行被加入的block__CFRunLoopDoBlocks(runloop, currentMode);/// 4. RunLoop 触发 Source0 (非port) 回调。sourceHandledThisLoop = __CFRunLoopDoSources0(runloop, currentMode, stopAfterHandle);/// 执行被加入的block__CFRunLoopDoBlocks(runloop, currentMode);/// 5. 如果有 Source1 (基于port) 处于 ready 状态,直接处理这个 Source1 然后跳转去处理消息。if (__Source0DidDispatchPortLastTime) {Boolean hasMsg = __CFRunLoopServiceMachPort(dispatchPort, &msg)if (hasMsg) goto handle_msg;}/// 通知 Observers: RunLoop 的线程即将进入休眠(sleep)。if (!sourceHandledThisLoop) {__CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeWaiting);}/// 7. 调用 mach_msg 等待接受 mach_port 的消息。线程将进入休眠, 直到被下面某一个事件唤醒。/// ? 一个基于 port 的Source 的事件。/// ? 一个 Timer 到时间了/// ? RunLoop 自身的超时时间到了/// ? 被其他什么调用者手动唤醒__CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort) {mach_msg(msg, MACH_RCV_MSG, port); // thread wait for receive msg}/// 8. 通知 Observers: RunLoop 的线程刚刚被唤醒了。__CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopAfterWaiting);/// 收到消息,处理消息。handle_msg:/// 9.1 如果一个 Timer 到时间了,触发这个Timer的回调。if (msg_is_timer) {__CFRunLoopDoTimers(runloop, currentMode, mach_absolute_time())} /// 9.2 如果有dispatch到main_queue的block,执行block。else if (msg_is_dispatch) {__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg);} /// 9.3 如果一个 Source1 (基于port) 发出事件了,处理这个事件else {CFRunLoopSourceRef source1 = __CFRunLoopModeFindSourceForMachPort(runloop, currentMode, livePort);sourceHandledThisLoop = __CFRunLoopDoSource1(runloop, currentMode, source1, msg);if (sourceHandledThisLoop) {mach_msg(reply, MACH_SEND_MSG, reply);}}/// 执行加入到Loop的block__CFRunLoopDoBlocks(runloop, currentMode);if (sourceHandledThisLoop && stopAfterHandle) {/// 进入loop时参数说处理完事件就返回。retVal = kCFRunLoopRunHandledSource;} else if (timeout) {/// 超出传入参数标记的超时时间了retVal = kCFRunLoopRunTimedOut;} else if (__CFRunLoopIsStopped(runloop)) {/// 被外部调用者强制停止了retVal = kCFRunLoopRunStopped;} else if (__CFRunLoopModeIsEmpty(runloop, currentMode)) {/// source/timer/observer一个都没有了retVal = kCFRunLoopRunFinished;}/// 如果没超时,mode里没空,loop也没被停止,那继续loop。} while (retVal == 0);}/// 10. 通知 Observers: RunLoop 即将退出。__CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);
}

可以看到,实际上 RunLoop 就是这样一个函数,其内部是一个 do-while 循环。当你调用 CFRunLoopRun() 时,线程就会一直停留在这个循环里;直到超时或被手动停止,该函数才会返回。

CFRunLoopRef之系统默认注册的5个Mode:

CFRunLoop {current mode = kCFRunLoopDefaultModecommon modes = {UITrackingRunLoopModekCFRunLoopDefaultMode}common mode items = {// source0 (manual)CFRunLoopSource {order =-1, {callout = _UIApplicationHandleEventQueue}}CFRunLoopSource {order =-1, {callout = PurpleEventSignalCallback }}CFRunLoopSource {order = 0, {callout = FBSSerialQueueRunLoopSourceHandler}}// source1 (mach port)CFRunLoopSource {order = 0,  {port = 17923}}CFRunLoopSource {order = 0,  {port = 12039}}CFRunLoopSource {order = 0,  {port = 16647}}CFRunLoopSource {order =-1, {callout = PurpleEventCallback}}CFRunLoopSource {order = 0, {port = 2407,callout = _ZL20notify_port_callbackP12__CFMachPortPvlS1_}}CFRunLoopSource {order = 0, {port = 1c03,callout = __IOHIDEventSystemClientAvailabilityCallback}}CFRunLoopSource {order = 0, {port = 1b03,callout = __IOHIDEventSystemClientQueueCallback}}CFRunLoopSource {order = 1, {port = 1903,callout = __IOMIGMachPortPortCallback}}// OvserverCFRunLoopObserver {order = -2147483647, activities = 0x1, // Entrycallout = _wrapRunLoopWithAutoreleasePoolHandler}CFRunLoopObserver {order = 0, activities = 0x20,          // BeforeWaitingcallout = _UIGestureRecognizerUpdateObserver}CFRunLoopObserver {order = 1999000, activities = 0xa0,    // BeforeWaiting | Exitcallout = _afterCACommitHandler}CFRunLoopObserver {order = 2000000, activities = 0xa0,    // BeforeWaiting | Exitcallout = _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv}CFRunLoopObserver {order = 2147483647, activities = 0xa0, // BeforeWaiting | Exitcallout = _wrapRunLoopWithAutoreleasePoolHandler}// TimerCFRunLoopTimer {firing = No, interval = 3.1536e+09, tolerance = 0,next fire date = 453098071 (-4421.76019 @ 96223387169499),callout = _ZN2CAL14timer_callbackEP16__CFRunLoopTimerPv (QuartzCore.framework)}},modes = {CFRunLoopMode  {sources0 =  { /* same as 'common mode items' */ },sources1 =  { /* same as 'common mode items' */ },observers = { /* same as 'common mode items' */ },timers =    { /* same as 'common mode items' */ },},CFRunLoopMode  {sources0 =  { /* same as 'common mode items' */ },sources1 =  { /* same as 'common mode items' */ },observers = { /* same as 'common mode items' */ },timers =    { /* same as 'common mode items' */ },},CFRunLoopMode  {sources0 = {CFRunLoopSource {order = 0, {callout = FBSSerialQueueRunLoopSourceHandler}}},sources1 = (null),observers = {CFRunLoopObserver >{activities = 0xa0, order = 2000000,callout = _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv})},timers = (null),},
//CFRunLoopMode  {sources0 = {CFRunLoopSource {order = -1, {callout = PurpleEventSignalCallback}}},sources1 = {CFRunLoopSource {order = -1, {callout = PurpleEventCallback}}},observers = (null),timers = (null),},
//CFRunLoopMode  {sources0 = (null),sources1 = (null),observers = (null),timers = (null),}}
}

可以看到,系统默认注册了5个Mode:

  1. kCFRunLoopDefaultMode: App的默认 Mode,通常主线程是在这个 Mode 下运行的。

  2. UITrackingRunLoopMode: 界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响。

  3. UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用。

  4. GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到。

  5. kCFRunLoopCommonModes: 这是一个占位的 Mode,没有实际作用。

当 RunLoop 进行回调时,一般都是通过一个很长的函数调用出去 (call out), 当你在你的代码中下断点调试时,通常能在调用栈上看到这些函数。下面是这几个函数的整理版本,如果你在调用栈中看到这些长函数名,在这里查找一下就能定位到具体的调用地点了

{
// 1. 通知Observers,即将进入RunLoop
// 此处有Observer会创建AutoreleasePool: _objc_autoreleasePoolPush();
//  __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(kCFRunLoopEntry);do {
//
// 2. 通知 Observers: 即将触发 Timer 回调。
//      __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(kCFRunLoopBeforeTimers);
// 3. 通知 Observers: 即将触发 Source (非基于port的,Source0) 回调。
//      __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(kCFRunLoopBeforeSources);
//      __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__(block);
//
// 4. 触发 Source0 (非基于port的) 回调。
//      __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__(source0);
//      __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__(block);
///// 6. 通知Observers,即将进入休眠
// 此处有Observer释放并新建AutoreleasePool: _objc_autoreleasePoolPop(); _objc_autoreleasePoolPush();
//      __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(kCFRunLoopBeforeWaiting);
//
// 7. sleep to wait msg.mach_msg() -> mach_msg_trap();
//       
//
// 8. 通知Observers,线程被唤醒
//      __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(kCFRunLoopAfterWaiting);
//
// 9. 如果是被Timer唤醒的,回调Timer
//  __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__(timer);
//  
// 9. 如果是被dispatch唤醒的,执行所有调用 dispatch_async 等方法放入main queue 的 block
//    __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(dispatched_block);
//
// 9. 如果如果Runloop是被 Source1 (基于port的) 的事件唤醒了,处理这个事件
//    __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__(source1);
//
//} while (...);
//
// 10. 通知Observers,即将退出RunLoop
// 此处有Observer释放AutoreleasePool: _objc_autoreleasePoolPop();
//   __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(kCFRunLoopExit);
}

AutoreleasePoolApp启动后,苹果在主线程 RunLoop 里注册了两个 Observer,其回调都是 _wrapRunLoopWithAutoreleasePoolHandler()。第一个 Observer 监视的事件是 Entry(即将进入Loop),其回调内会调用 _objc_autoreleasePoolPush() 创建自动释放池。其 order 是-2147483647,优先级最高,保证创建释放池发生在其他所有回调之前。第二个 Observer 监视了两个事件: BeforeWaiting(准备进入休眠) 时调用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 释放旧的池并创建新池;Exit(即将退出Loop) 时调用 _objc_autoreleasePoolPop() 来释放自动释放池。这个 Observer 的 order 是 2147483647,优先级最低,保证其释放池子发生在其他所有回调之后。在主线程执行的代码,通常是写在诸如事件回调、Timer回调内的。这些回调会被 RunLoop 创建好的 AutoreleasePool 环绕着,所以不会出现内存泄漏,开发者也不必显示创建 Pool 了。

事件响应苹果注册了一个 Source1 (基于 mach port 的) 用来接收系统事件,其回调函数为 __IOHIDEventSystemClientQueueCallback()。当一个硬件事件(触摸/锁屏/摇晃等)发生后,首先由 IOKit.framework 生成一个 IOHIDEvent 事件并由 SpringBoard 接收。这个过程的详细情况可以参考这里。SpringBoard 只接收按键(锁屏/静音等),触摸,加速,接近传感器等几种 Event,随后用 mach port 转发给需要的App进程。随后苹果注册的那个 Source1 就会触发回调,并调用 _UIApplicationHandleEventQueue() 进行应用内部的分发。_UIApplicationHandleEventQueue() 会把 IOHIDEvent 处理并包装成 UIEvent 进行处理或分发,其中包括识别 UIGesture/处理屏幕旋转/发送给 UIWindow 等。通常事件比如 UIButton 点击、touchesBegin/Move/End/Cancel 事件都是在这个回调中完成的。

手势识别当上面的 _UIApplicationHandleEventQueue() 识别了一个手势时,其首先会调用 Cancel 将当前的 touchesBegin/Move/End 系列回调打断。随后系统将对应的 UIGestureRecognizer 标记为待处理。苹果注册了一个 Observer 监测 BeforeWaiting (Loop即将进入休眠) 事件,这个Observer的回调函数是 _UIGestureRecognizerUpdateObserver(),其内部会获取所有刚被标记为待处理的 GestureRecognizer,并执行GestureRecognizer的回调。当有 UIGestureRecognizer 的变化(创建/销毁/状态改变)时,这个回调都会进行相应处理。

界面更新当在操作 UI 时,比如改变了 Frame、更新了 UIView/CALayer 的层次时,或者手动调用了 UIView/CALayer 的 setNeedsLayout/setNeedsDisplay方法后,这个 UIView/CALayer 就被标记为待处理,并被提交到一个全局的容器去。苹果注册了一个 Observer 监听 BeforeWaiting(即将进入休眠) 和 Exit (即将退出Loop) 事件,回调去执行一个很长的函数:_ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv()。这个函数里会遍历所有待处理的 UIView/CAlayer 以执行实际的绘制和调整,并更新 UI 界面。

这个函数内部的调用栈大概是这样的:

_ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv()QuartzCore:CA::Transaction::observer_callback:CA::Transaction::commit();CA::Context::commit_transaction();CA::Layer::layout_and_display_if_needed();CA::Layer::layout_if_needed();[CALayer layoutSublayers];[UIView layoutSubviews];CA::Layer::display_if_needed();[CALayer display];[UIView drawRect];

相关文章:

倒计时 3 天!「2019 嵌入式智能国际大会」全日程大公开!

立即抢购:https://t.csdnimg.cn/otBk还有3天,大伙期待的「2019嵌入式智能国际大会」正式开幕了!2019年12月6日-7日,我们在深圳市人才研修院见!大会以“万物互联泛在智能”为主题,邀请30位海内外顶级专家作为…

Fckeditor PHP/ASP File Upload Vul

目录 1. 漏洞描述 2. 漏洞触发条件 3. 漏洞影响范围 4. 漏洞代码分析 5. 防御方法 6. 攻防思考 1. 漏洞描述 FCKeditor是目前最优秀的可见即可得网页编辑器之一,它采用JavaScript编写。具备功能强大、配置容易、跨浏览器、支持多种编程语言、开源等特点。它非常流行…

iOS App上架流程(2016详细版),真心很详细。

一、前言:作为一名iOSer,把开发出来的App上传到App Store是必要的。下面就来详细讲解一下具体流程步骤。二、准备:一个已付费的开发者账号(账号类型分为个人(Individual)、公司(Company&#xf…

飞机的“黑色十分钟”能被人工智能消灭吗?

【导读】近年来,“AI的应用和落地”逐渐成了具化的关键词,它和很多事物很多行业结合在一起,形成了奇妙的“化学反应”。例如,在日常生活中,AI可以推送我们喜欢的新闻或视频,可以在拍照的时候识别场景提升照…

Jenkins简介及在Windows上的简单使用示例

Jenkins是一款开源CI(Continuous Integration,持续集成)&CD(Continuous Delivery,持续交付)软件,用于自动化各种任务,包括构建、测试和部署软件,源码在https://github.com/jenkinsci/jenkins ,License为…

IOS开发之数据sqlite使用

一、引入工具包引入工具包libsqlite3.dylib,该工具包为C语言工具包。 二、代码操作数据库1、创建并且链接数据库 - (void) _connectDB{//1>获取沙盒路径作为数据库创建时候的初始化路径NSString * pathNSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDom…

通过Dockerfile构建Docker镜像

Dockerfile是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建. Dockerfile支持Shell类的行尾添加"\"的命令换行方式,以及行首"#"进行注释的格式. 使用Dockerfile构建Docker镜像时注…

华为腾讯百度众安微众360大咖齐聚,2019中国区块链开发者大会首批议程曝光!...

作者 | Aholiab出品 | 区块链大本营(blockchain_camp)随着区块链被定义为国家战略,区块链技术得到升温。据有关国际研究机构预测,三年后全球区块链市场规模将达到139.6亿美元(约合986.23亿元人民币)&#x…

iOS GCD使用

dispatch_queue_t queue dispatch_queue_create("testQueue", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ // 追加任务1[self.hud show:YES];for (int i 0; i < 2; i) { [NSThread sleepForTimeInterval:2]; // 模拟耗时操作[self reqHopwork];} })…

01 http协议概念及工作流程

一&#xff1a;HTTP协议 重要性: 无论是以后用webserverice ,还是用rest做大型架构,都离不开对HTTP协议的认识. 甚至可以简化的说: webservice http协议XML Rest HTTP协议 json 各种API,也一般是用httpXML/json来实现的. 往小说:做采集,小偷站,也需要对HTTP协议有所了解, 以…

iOS原生与html交互 使用第三方WebViewJavascriptBridge

HTML页面代码 <!DOCTYPE html><html xmlns:http"http://www.w3.org/1999/xhtml"><head> <meta charset"utf-8"> <title>迎新好礼</title> <meta name"viewport" content"widthdevice-width,initial…

Docker容器中挂载NFS共享目录

之前在https://blog.csdn.net/fengbingchun/article/details/110561129 介绍过使用Dockerfile构建ubuntu 16.04镜像,并在容器中编译执行Messy_Test项目.这里介绍下如何在容器中挂载NFS服务器上的共享目录. Dockerfile内容如下&#xff1a; FROM ubuntu:16.04 LABEL maintaine…

倒计时1天 | 2019 中国大数据技术大会(BDTC)报名通道即将关闭(附参会提醒)...

2019年12月5-7日&#xff0c;由中国计算机学会主办&#xff0c;CCF 大数据专家委员会承办&#xff0c;CSDN、中科天玑数据科技股份有限公司协办的中国大数据技术大会&#xff08;BDTC 2019&#xff09;将于北京长城饭店隆重举行。届时&#xff0c;超过百位顶尖技术专家将齐聚于…

Android TextView的一些小知识

2019独角兽企业重金招聘Python工程师标准>>> 1.设置文字行距 android:lineSpacingExtra"8dp" 或者 android:lineSpacingMultiplier"1.5" 2.设置字间距 在API21里可以设置 API 21 android:letterSpacing"0.5f" //字间距 注意&#x…

iOS WKWebView带进度条封装(只用传入url,可改变进度条颜色)

1 NSTimeraddition.h #import <Foundation/Foundation.h> interface NSTimer (addition) /** 暂停时间 */ - (void)w_pauseTime; /** 获取内容所在当前时间 */ - (void)w_webPageTime; /** 当前时间 time 秒后的时间 */ - (void)w_webPageTimeWithTimeInterval:(NSTimeIn…

Ubuntu上配置VS Code调试C++

直接使用GDB在Ubuntu上调试C code&#xff0c;有时不是很方便&#xff0c;这里介绍下在Ubuntu上通过Visual Studio Code调试C code操作步骤&#xff0c;通过CMake编译。 安装所需依赖&#xff1a; (1).在Ubuntu上安装Visual Studio Code最新稳定版本1.51.1&#xff1b; (2).…

因果关系是通向强AI的阶梯or作用被夸大?

整理 | 夕颜出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;一直以来&#xff0c;机器学习和统计学之间的界限就比较模糊&#xff0c;比如诺奖得主托马斯萨金特就曾经说过人工智能其实就是统计学&#xff0c;只不过用了一个很华丽的辞藻。但同时也有人认为&#xff0…

Android中设置TextView的颜色setTextColor

tv.setTextColor(Color.parseColor("#FFFFFF")); tv.setTextColor(Color.WHITE); tv.setTextColor(Color.rgb(255, 255, 255)); //注意Color是大写C&#xff0c;不是color.holo_orange_dark,这样错误并没效果的 tv.setBackgroundResource(R.drawable.icon_bg_rectan…

iOS 跑马灯封装(带点击事件)

1.WAdvertScrollView.h#import <UIKit/UIKit.h>class WAdvertScrollView;typedef enum : NSUInteger {/// 一行文字滚动样式WAdvertScrollViewStyleNormal,/// 二行文字滚动样式WAdvertScrollViewStyleMore, } WAdvertScrollViewStyle;protocol WAdvertScrollViewDelegat…

日期与unix时间戳之间的转换C++实现

之前在https://blog.csdn.net/fengbingchun/article/details/107023645 中介绍过gmtime和localtime的区别&#xff0c;这里介绍下日期与Unix时间戳之间转换的实现&#xff0c;其中也会用到这两个函数。 Unix时间戳(Unix timestamp)&#xff1a;是一种时间表示方式&#xff0c;…

模型训练完才是业务的开始?说说模型监控 | CSDN博文精选

扫码参与CSDN“原力计划”作者 | A字头来源 | 数据札记倌(ID:Data_Groom)“模型训练结束后才是业务真正的开始”简述每次模型训练完成后&#xff0c;并不意味着项目的结束&#xff0c;在训练模型后&#xff0c;我们还需要将其稳定上线&#xff0c;然后部署一套相应的监控体系&a…

后端码农谈前端(CSS篇)第一课:CSS概述

一、从扮演浏览器开始 扮演浏览器是Head First图书中很有意义的一个环节。可作者忘记了告诉我们扮演浏览器的台本。我们从这里开始。 上图是webkit内核渲染html和css的流程图。从该图我们可以知道以下几个关键信息&#xff1a; HTML的解析过程和CSS的解析过程是独立完成的。HTM…

远场语音识别错误率降低30%,百度提基于复数CNN网络的新技术

【12月公开课预告】&#xff0c;入群直接获取报名地址12月11日晚8点直播主题&#xff1a;人工智能消化道病理辅助诊断平台——从方法到落地12月12日晚8点直播&#xff1a;利用容器技术打造AI公司技术中台12月17日晚8点直播主题&#xff1a;可重构计算&#xff1a;能效比、通用性…

深度神经网络中的局部响应归一化LRN简介及实现

Alex、Hinton等人在2012年的NIPS论文《ImageNet Classification with Deep Convolutional Neural Networks》中将LRN应用于深度神经网络中(AlexNet)。论文见&#xff1a;http://www.cs.toronto.edu/~hinton/absps/imagenet.pdf &#xff0c;截图如下&#xff1a; 公式解释&…

iOS 被拒解析

原因&#xff1a; Your app uses the "prefs:root" non-public URL scheme, which is a private entity. The use of non-public APIs is not permitted on the App Store because it can lead to a poor user experience should these APIs change.Continuing to us…

MSSQL数据库统计所有表的记录数

今天需要筛选出来库中行数不为零的表&#xff0c;于是动手写下了如下存储过程。 CREATE PROCEDURE TableCount AS BEGIN SET NOCOUNT ON DECLARE t1 AS TABLE(id INT IDENTITY,NAME NVARCHAR(50),RowsCount INT) DECLARE indexid AS INT DECLARE maxid AS INT DECLARE count A…

经典网络AlexNet介绍

AlexNet经典网络由Alex Krizhevsky、Hinton等人在2012年提出&#xff0c;发表在NIPS&#xff0c;论文名为《ImageNet Classification with Deep Convolutional Neural Networks》&#xff0c;论文见&#xff1a;http://www.cs.toronto.edu/~hinton/absps/imagenet.pdf &#xf…

微软张若非:搜索引擎和广告系统,那些你所不知的AI落地技术

【12月公开课预告】&#xff0c;入群直接获取报名地址12月11日晚8点直播主题&#xff1a;人工智能消化道病理辅助诊断平台——从方法到落地12月12日晚8点直播&#xff1a;利用容器技术打造AI公司技术中台12月17日晚8点直播主题&#xff1a;可重构计算&#xff1a;能效比、通用性…

iOS 之 IQKeyboardManager 解决使用UITableView 界面上移问题

- (void)viewWillAppear:(BOOL)animated {[IQKeyboardManager sharedManager].enable NO;}- (void)viewWillDisappear:(BOOL)animated{[super viewWillDisappear:animated];[IQKeyboardManager sharedManager].enable YES; }

excel增加上一列的数值(日期)

TEXT(D2-1,"m月d日") 有年的话就是 TEXT(D2-1,"yyyy年m月d日") D2就是参照日期转载于:https://www.cnblogs.com/hont/p/4352877.html