原文地址:http://www.tanhao.me/pieces/358.html/
概念
为了在单一进程中充分发挥多核的优势,我们有必要使用多线程技术(我们没必要去提多进程,这玩意儿和GCD没关系)。在低层,GCD全局dispatch queue仅仅是工作线程池的抽象。这些队列中的Block一旦可用,就会被dispatch到工作线程中。提交至用户队列的Block最终也会通过全局队列进入相同的工作线程池(除非你的用户队列的目标是主线程,但是为了提高运行速度,我们绝不会这么干)。
有两种途径来通过GCD“榨取”多核心系统的性能:将单一任务或者一组相关任务并发至全局队列中运算;将多个不相关的任务或者关联不紧密的任务并发至用户队列中运算;
全局队列
设想下面的循环:
for(id obj in array) [self doSomethingIntensiveWith:obj];
假定 -doSomethingIntensiveWith: 是线程安全的且可以同时执行多个.一个array通常包含多个元素,这样的话,我们可以很简单地使用GCD来平行运算:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); for(id obj in array) dispatch_async(queue, ^{ [self doSomethingIntensiveWith:obj]; });
如此简单,我们已经在多核心上运行这段代码了。
当然这段代码并不完美。有时候我们有一段代码要像这样操作一个数组,但是在操作完成后,我们还需要对操作结果进行其他操作:
for(id obj in array) [self doSomethingIntensiveWith:obj]; [self doSomethingWith:array];
这时候使用GCD的 dispatch_async 就悲剧了.我们还不能简单地使用dispatch_sync来解决这个问题, 因为这将导致每个迭代器阻塞,就完全破坏了平行计算。
解决这个问题的一种方法是使用dispatch group。一个dispatch group可以用来将多个block组成一组以监测这些Block全部完成或者等待全部完成时发出的消息。使用函数dispatch_group_create来创建,然后使用函数dispatch_group_async来将block提交至一个dispatch queue,同时将它们添加至一个组。所以我们现在可以重新代码:
dispatch_queue_t queue = dispatch_get_global_qeueue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); for(id obj in array) dispatch_group_async(group, queue, ^{ [self doSomethingIntensiveWith:obj]; }); dispatch_group_wait(group, DISPATCH_TIME_FOREVER); dispatch_release(group); [self doSomethingWith:array];
如果这些工作可以异步执行,那么我们可以更风骚一点,将函数-doSomethingWith:放在后台执行。我们使用dispatch_group_async函数建立一个block在组完成后执行:
dispatch_queue_t queue = dispatch_get_global_qeueue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); for(id obj in array) dispatch_group_async(group, queue, ^{ [self doSomethingIntensiveWith:obj]; }); dispatch_group_notify(group, queue, ^{ [self doSomethingWith:array]; }); dispatch_release(group);
不仅所有数组元素都会被平行操作,后续的操作也会异步执行,并且这些异步运算都会将程序的其他部分考虑在内。注意如果-doSomethingWith:需要在主线程中执行,比如操作GUI,那么我们只要将main queue而非全局队列传给dispatch_group_notify函数就行了。
对于同步执行,GCD提供了一个简化方法叫做dispatch_apply。这个函数调用单一block多次,并平行运算,然后等待所有运算结束,就像我们想要的那样:
dispatch_queue_t queue = dispatch_get_global_qeueue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_apply([array count], queue, ^(size_t index){ [self doSomethingIntensiveWith:[array objectAtIndex:index]]; }); [self doSomethingWith:array];
这很棒,但是异步咋办?dispatch_apply函数可是没有异步版本的。但是我们使用的可是一个为异步而生的API啊!所以我们只要用dispatch_async函数将所有代码推到后台就行了:
dispatch_queue_t queue = dispatch_get_global_qeueue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ dispatch_apply([array count], queue, ^(size_t index){ [self doSomethingIntensiveWith:[array objectAtIndex:index]]; }); [self doSomethingWith:array]; });
简单的要死!
这种方法的关键在于确定我们的代码是在一次对不同的数据片段进行相似的操作。如果你确定你的任务是线程安全的(不在本篇讨论范围内)那么你可以使用GCD来重写你的循环了,更平行更风骚。
要看到性能提升,你还得进行一大堆工作。比之线程,GCD是轻量和低负载的,但是将block提交至queue还是很消耗资源的——block需要被拷贝和入队,同时适当的工作线程需要被通知。不要将一张图片的每个像素作为一个block提交至队列,GCD的优点就半途夭折了。如果你不确定,那么请进行试验。将程序平行计算化是一种优化措施,在修改代码之前你必须再三思索,确定修改是有益的(还有确保你修改了正确的地方)。
Subsystem并发运算
前面的章节我们讨论了在程序的单个subsystem中发挥多核心的优势。下来我们要跨越多个子系统。
例如,设想一个程序要打开一个包含meta信息的文档。文档数据本身需要解析并转换至模型对象来显示,meta信息也需要解析和转换。但是,文档数据和meta信息不需要交互。我们可以为文档和meta各创建一个dispatch queue,然后并发执行。文档和meta的解析代码都会各自串行执行,从而不用考虑线程安全(只要没有文档和meta之间共享的数据),但是它们还是并发执行的。
一旦文档打开了,程序需要响应用户操作。例如,可能需要进行拼写检查、代码高亮、字数统计、自动保存或者其他什么。如果每个任务都被实现为在不同的dispatch queue中执行,那么这些任务会并发执行,并各自将其他任务的运算考虑在内(respect to each other),从而省去了多线程编程的麻烦。
使用dispatch source(下次我会讲到),我们可以让GCD将事件直接传递给用户队列。例如,程序中监视socket连接的代码可以被置于它自己的dispatch queue中,这样它会异步执行,并且执行时会将程序其他部分的运算考虑在内。另外,如果使用用户队列的话,这个模块会串行执行,简化程序。
结论
我们讨论了如何使用GCD来提升程序性能以及发挥多核系统的优势。尽管我们需要比较谨慎地编写并发程序,GCD还是使得我们能更简单地发挥系统的可用计算资源。
下一篇中,我们将讨论dispatch source,也就是GCD的监视内部、外部事件的机制。
该系列文章转载自:http://www.dreamingwish.com/
相关推荐
以下是对GCD的详细介绍: 一、基本概念 全称:Grand Central Dispatch 类型:基于C语言的底层API 所属库:libdispatch 用途:为并发代码在iOS和macOS的多核硬件上执行提供支持 二、核心优势 自动管理线程:GCD自动...
- **性能:** GCD具备高度集成的事件控制系统,能够响应多种事件,并将这些事件的处理代码并发执行。 3. **Dispatch Objects:** 虽然GCD是用C语言编写的,但它采用了面向对象的编程风格。GCD对象称为dispatch ...
在IT行业中,多线程是程序设计中的一个重要概念,特别是在...通过研究这个项目,开发者可以深入理解GCD的工作原理,提高自己的多线程编程技能,同时也能学习如何在实际项目中有效利用GCD来提升应用的性能和用户体验。
当向并发队列提交任务时,GCD会根据系统资源动态调整任务的执行,可能在一个核心上执行,也可能在多个核心上并发执行,这取决于任务的数量和系统的负载。 三、异步执行任务 在GCD中,可以使用`dispatch_async`函数...
3. 性能:GCD自动根据系统负载来增减线程数量,这就减少了上下午切换以及增加了计算效率。 三、Dispatch Objects Dispatch Objects是GCD的核心,GCD对象被称为dispatch object。Dispatch object像Cocoa对象一样是...
二、多线程 多线程是实现并发的一种方式,通过创建和管理多个执行线程,可以让应用程序在等待某个任务完成时执行其他任务。在GCD中,我们并不直接创建线程,而是向队列中添加任务。GCD会自动决定何时、在哪一个线程...
GCD的核心概念有队列(Dispatch Queue)和任务(Dispatch Work Item)。 1. **主队列(Main Queue)**:在主线程上执行任务,用于更新UI。 2. **并行队列(Concurrent Queue)**:可以在多个线程上并发地执行任务。...
GCD(Grand Central Dispatch)是 Apple 公司推出的一个并发编程模型,旨在简化多线程编程的复杂度,提高系统的性能和响应速度。 GCD 的核心是 Mach kernel,它是一个基于微内核的操作系统核心。Mach(kernel) 提供...
这篇博客文章《ios gcd》可能深入探讨了如何在iOS应用中利用GCD来优化性能和提高代码的可读性。 GCD的核心概念包括队列和任务。队列分为两种类型:串行队列和并行队列。串行队列按照任务的添加顺序逐一执行,而并行...
- 提高性能:通过自动调度,GCD可以充分利用多核处理器的优势,提高程序执行效率。 - 容易维护:使用Block语法,代码更简洁,易于理解和维护。 通过"GCDDemo"项目,开发者可以深入理解GCD的使用,包括如何创建...
GCD基于队列和任务的概念,允许开发者高效地管理并发任务,提高应用程序的性能。下面将详细阐述GCD的基础和延伸方法,以帮助你更好地理解和运用GCD。 1. **GCD基础概念** - **Dispatch Queue**:调度队列是GCD的...
在iOS开发中,多线程技术是不可或缺的一部分,它能够帮助我们提高应用程序的性能和用户体验。GCD(Grand Central Dispatch)是苹果推出的一种强大的多线程解决方案,它为开发者提供了简单而高效的方式来管理并发任务...
在iOS开发中,Grand Central Dispatch(GCD)是苹果提供的一种多线程解决方案,它能够帮助开发者有效地利用多核处理器的性能。GCD的核心概念包括队列和任务,本篇文章将深入探讨这两种核心元素,以及如何在实际项目...
标签"gcd"进一步确认了这个项目的核心是关于GCD计算的。而压缩包中还有一个名为"www.pudn.com.txt"的文件,这可能是来源链接或者一些说明文档,提供了更多关于此设计的上下文信息,比如设计者的注释、原始出处或者是...
GCD(Grand Central Dispatch)是Apple在OS X和iOS系统中引入的一种多线程处理技术,旨在简化并发编程,提高应用程序的性能和响应速度。GCD利用了操作系统底层的调度机制,允许开发者以一种声明式的方式处理并发任务...
在iOS和macOS开发中,Grand Central Dispatch(GCD)是一种强大的多线程技术,用于管理应用程序的并发性。GCD是苹果操作系统内核的一部分,它抽象了线程管理和调度,使得开发者可以更加专注于任务本身,而不是底层的...
**GCD(Grand Central Dispatch)**是Apple在Mac OS X v10.6 Snow Leopard及后续版本中引入的一种多线程技术,它极大地简化了并发编程。GCD是基于C语言的,但在Objective-C和Swift中也有良好的支持,是苹果操作系统...
在本文中,我们将深入探讨如何在裸机环境下编写和理解一个使用MIPS(Microprocessor without Interlocked Pipeline Stages,无锁步管道阶段微处理器)指令集实现的最大公约数(Greatest Common Divisor, GCD)程序。...
总结,GCD在iOS开发中扮演着重要的角色,通过合理地使用GCD,开发者可以编写出高效、稳定的多线程代码,提升应用的性能和用户体验。深入理解并熟练运用GCD,是每个iOS开发者必备的技能。通过阅读...