使用dispatch_async在Swift中并发分析数组

2024-04-02

我正在尝试使用 GCD 的后台线程同时分析照片。这是我写的代码:

dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
    for (var i = 0; i < 8; i++)
    {
        let color = self.photoAnalyzer.analyzeColors(imageStrips[i])
        colorList.append(color)
    }
}

为了澄清变量名称,以下是它们的描述:

photoAnalyzer是我编写的一个类的实例Analyzer它包含处理图像的所有方法。

analyzeColors是里面的一个方法Analyzer执行大部分分析并返回带有传入图像的主色的字符串的类

imageStrips是一个数组UIImage组成原始图像的部分

colorList是一个字符串数组,存储了返回值analyzeColor图像每个部分的方法。

上面的代码从for循环只访问一张图像imageList一次。我想做的是分析每个图像imageStrips同时,但我不知道如何去做。

任何建议将不胜感激。如果您想查看所有代码来进一步帮助我,我可以发布一个 GitHub 链接。

EDIT这是我更新的代码,用于同时处理 8 个处理器。

dispatch_apply(8, imageQueue) { numStrips -> Void in
    let color = self.photoAnalyzer.analyzeColors(imageStrips[numStrips])
    colorList.append(color)
}

但是,如果我尝试使用超过 8 个,代码实际上运行速度会比顺序运行慢。


有几种方法可以做到这一点,但在我们开始之前有一些观察结果:

  • 为了尽量提高性能,如果您进行任何并发处理,请注意,无法保证它们的完成顺序。因此一个简单的colorList.append(color)如果它们出现的顺序很重要,则模式将不起作用。您可以预先填充colorList然后让每次迭代简单地做colorList[i] = color或者你可以使用字典。 (显然,如果顺序不重要,那么这并不重要。)

  • 由于这些迭代将同时运行,因此您需要同步更新colorList。所以你的昂贵analyzeColors在后台队列上并发,但使用串行队列来更新colorList,以确保多个更新不会相互重叠。

  • 在进行并发处理时,存在收益递减点。例如,将一个复杂的任务分解为 2-4 个并发循环可能会带来一些性能优势,但如果您开始过多地增加并发线程的数量,您会发现这些线程的开销开始对性能产生不利影响。因此,请使用不同程度的并发性进行基准测试,并且不要假设“更多线程”总是更好。

就如何实现这一点而言,有两种基本技术:

  1. 如果你看到同时执行循环迭代 https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW23 in the 并发编程指南:调度队列指南,他们谈论dispatch_apply,正是为此目的而设计的,运行for同时循环。

    colorList = [Int](count: 8, repeatedValue: 0)  // I don't know what type this `colorList` array is, so initialize this with whatever type makes sense for your app
    
    let queue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)
    
    let qos_attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0)
    let syncQueue = dispatch_queue_create("com.domain.app.sync", qos_attr)
    
    dispatch_apply(8, queue) { iteration in
        let color = self.photoAnalyzer.analyzeColors(imageStrips[iteration])
        dispatch_sync(syncQueue) {
            colorList[iteration] = color
            return
        }
    }
    
    // you can use `colorList` here
    

    请注意,虽然这些迭代同时运行,但整个dispatch_apply循环相对于您启动它的队列同步运行。这意味着您不会希望从主线程调用上面的代码(我们永远不想阻塞主线程)。因此可能希望将整个事情分派到某个后台队列。

    顺便一提,dispatch_applyWWDC 2011 视频中对此进行了讨论街区和大中央调度的实践 https://developer.apple.com/videos/wwdc/2011/?id=308.

  2. 另一种常见模式是创建一个调度组,使用该组将任务调度到并发队列,并指定一个dispatch_group_notify指定完成后您想要执行的操作。

    colorList = [Int](count: 8, repeatedValue: 0)  // I don't know what type this `colorList` array is, so initialize this with whatever type makes sense for your app
    
    let group = dispatch_group_create()
    let queue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)
    
    let qos_attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0)
    let syncQueue = dispatch_queue_create("com.domain.app.sync", qos_attr)
    
    for i in 0 ..< 8 {
        dispatch_group_async(group, queue) {
            let color = self.photoAnalyzer.analyzeColors(imageStrips[i])
            dispatch_sync(syncQueue) {
                colorList[i] = color
                return
            }
        }
    }
    
    dispatch_group_notify(group, dispatch_get_main_queue()) {
        // use `colorList` here
    }
    
    // but not here (because the above code is running asynchronously)
    

    这种方法可以避免完全阻塞主线程,但您必须小心不要添加太多并发分派任务(因为工作线程是非常有限的资源)。

在这两个示例中,我创建了一个专用串行队列,用于将更新同步到colorList。这可能有点矫枉过正了。如果您没有阻塞主队列(无论如何都不应该这样做),您可以将此同步代码分派到主队列(这是一个串行队列)。但为此目的使用专用串行队列可能更精确。如果这是我要从多个线程不断交互的东西,我会使用读写器模式。但这对于这种情况来说可能已经足够了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用dispatch_async在Swift中并发分析数组 的相关文章

  • 存档期间的位码编译永远不会完成

    我正在准备一个通过 Test Flight 进行临时分发的应用程序 我已经 成功 完成了这篇 Ray Wenderlich 文章中的所有准备步骤 https www raywenderlich com 48750 testflight sd
  • iOS 无状态/无值进度条?

    我希望在 iOS 中获得无状态 无值的 UIProgressView 或其他类型的进度条 我尝试查找一些文档 但找不到与我的问题相关的任何内容 如果你们有任何建议 我很想听听 Thanks Shai iOS s UI进度视图 https d
  • 如何在 Swift Playground 中使用 Carthage 导入的框架

    我有一个快速项目 其中通过迦太基添加了一些框架 是否可以在项目内部的游乐场中使用这些框架以及如何使用它 因为 import Argo 不起作用 这在某个时候停止工作了 叹 我现在做的是 创建 macOS gt 命令行工具 创建一个购物车文件
  • 如何在 IOS 中以编程方式滚动 UICollectionViewCell?

    我有一个垂直的UICollectionView每个细胞占据整个self view frame我可以轻松地向上滑动以翻页到下一个单元格 但我想通过按按钮来执行相同的操作 我尝试过使用 void setContentOffset CGPoint
  • 我何时以及为什么要使用 ARC 将局部变量声明为 __weak?

    Mike Ash 撰写了 ARC 简介 http www mikeash com pyblog friday qa 2011 09 30 automatic reference counting html他在那里介绍了这样的内容 weak
  • 更改 UIImageView 的位置

    我怎样才能为 UIImageView 做一个简单的位置改变 假设当前坐标是 x 20 和 y 30 我想将其移至 x 100 和 y 100 可以制作运动动画吗 你需要改变它的CGFrameUIImageView就像这样 imageView
  • Swift - 如何复制包含引用类型的数组

    我正在尝试复制数组及其值 为什么两个数组都引用同一个变量 您可以在 Playground 中尝试此操作 var view UIView view tag 1 var a UIView var b UIView a append view b
  • 如何在 RxSwift 中取消订阅 Observable?

    我想在 RxSwift 中取消订阅 Observable 为了做到这一点 我曾经将 Disposable 设置为 nil 但在我看来 更新到 RxSwift 3 0 0 beta 2 后 这个技巧不起作用 我无法取消订阅 Observabl
  • FileSystemWatcher 在队列中丢失文件

    我写了一个FileSystemWatcher为每个文件调用一次 pgm 但我的一些文件丢失了 我只用 10 11 个文件测试了代码 文件的删除会被正确记录 但创建不会被正确记录 某些文件未记录 我的 TASK 实施可能存在问题吗 或者有什么
  • 如何去除 UIImageView 遮罩后的透明区域?

    在我的一个 iOS 应用程序中 我尝试使用以下命令剪切图像的一部分CGImageMask 我已成功使用以下代码屏蔽图像 UIImage maskImage UIImage referenceImage withMask UIImage ma
  • 使用 swift,是否可以访问辅助功能中的反转颜色功能?

    苹果已经在手机中添加了一般 gt 辅助功能 gt 反转颜色的功能 我可以以某种方式在我的程序中使用它 例如当用户触摸屏幕时颜色反转吗 我不知道有什么方法可以自动执行此操作 但您可以使用 UIColor 上的扩展并访问子视图自行反转颜色 ex
  • CLGeocoder reverseGeocodeLocation 返回“kCLErrorDomain 错误 9”

    我正在根据本文开发具有反向地理编码功能的 iOS 应用程序 地理编码教程 http jonathanfield me jons blog clgeocoder example html 但是当我在模拟器上进行这样的测试时 我收到 kCLEr
  • UIButton 和滑动手势

    我有一个UIView有两个UIButton每侧 左侧和右侧 都有 s 和UIImageView在中心 点击任一按钮都会改变UIImageView那行得通 我想要滑动的能力UIView以及它改变UIImageView 现在 您必须在UIIma
  • 在自定义对象中映射 JSON 对象

    我一直在搜索是否可以获取 JSON 字典或数组并将其直接映射到属性与 JSON 标签同名的自定义对象中 但我没有找到任何相关信息 我一直在手动解析 JSON 字典 如下所示 id deserializedObj nil id jsonObj
  • 反应本机套接字 io 没有从客户端发出事件

    尝试将socket io client与react native 现在是ios 一起使用 到目前为止 连接 从客户端接收服务器端事件似乎工作正常 但是我似乎无法从客户端发出任何事件 Client var socket io http loc
  • 图像高斯模糊 - iOS 8

    我有一个移动的背景图像 我想模糊它的底部 我would只用 Photoshop 就能做到 但由于图像会移动 效果不太好 这就是我的意思 看图片底部 基本上就像底座对 iPhone 的影响一样 我使用的是 iOS 8 但不是 Swift 我根
  • MPMediaItemPropertyAssetURL 仅针对 iPhone 5s 返回 null

    我一直在使用以下代码从 MPMediaItemPickerController 返回的 MPMediaItem 对象中提取资产 url 以便我可以将音乐文件从用户 iPhone itunes 音乐库复制到文档文件夹进行处理 但在 iPhon
  • 添加到 Xcode App 时,Bazel 框架抛出“无法检查应用程序包”

    我正在使用 Bazel 构建基于 MediaPipe 的人脸识别库 我正在使用apple xc框架 https github com bazelbuild rules apple blob master doc rules apple md
  • 错误 ITMS-90207 Apple Store 提交

    当我在模拟器或设备上运行我的应用程序时 用于调试和发布构建配置 它可以完美运行 但是当我尝试将我的应用程序提交到 Apple Store 时 出现以下错误 错误 ITMS 90207 捆绑包无效 APPNAME app 处的捆绑包确实 不包
  • 等高的 SwiftUI HStack

    我想要Text 111 具有相同的高度VStack包含 2222 和 333 struct Test7 View var body some View HStack alignment top Text 111 Shall have equ

随机推荐

  • 如何使用 Kotlin 就地过滤列表?

    在 Java 中 我可以使用以下代码从列表中删除项目 private void filterList List
  • 消除录音曲目中当前播放曲目的声音

    我希望使用远程 IO 进行音频录制和播放 我对核心音频的理解很差 因为我遵循惊人的音频开源 http theamazingaudioengine com 到目前为止 我可以使用相同的代码进行录制和播放 现在我尝试通过麦克风录制并通过 iPh
  • 特定接口上的 TCP/IP 连接

    我想使用两个网络路由之一连接到服务器 一个人会怎样做呢 我在 Google 上搜索了很多 常见的答案是修改路由表 但这并没有什么帮助 因为目的地只有一个 IP 地址 大多数示例都具有具有单个网卡的客户端和具有多个网卡的服务器 但在本例中情况
  • Shell 正则表达式到行尾

    我有一个像这样的小例子的文件 mode dev 该文件中某处的注释中有一个 变量 我想在 Shell 脚本中使用正则表达式获取值 到目前为止我的代码 bin bash conf lt etc test conf Get the file c
  • 队列上的 IEnumerable 迭代器是否应该使项目出列

    我创建了一个自定义通用队列 它实现了通用 IQueue 接口 该接口使用 System Collections Generic 命名空间中的通用队列作为私有内部队列 示例已清除不相关的代码 public interface IQueue
  • 您应该如何从源代码控制构建数据库?

    SO 社区 wiki 上有一些关于数据库对象是否应该进行版本控制的讨论 然而 我还没有看到太多关于为数据库对象创建构建自动化过程的最佳实践的讨论 对于我的团队来说 这一直是一个有争议的讨论点 特别是因为开发人员和 DBA 在评估数据库部署自
  • 如何在 ElasticSearch 中基于正则表达式过滤令牌

    对于 ElasticSearch 查询 我们希望以不同的方式处理单词 即仅由字母组成的标记 和非单词 为此 我们尝试定义两个分析器 返回单词或非单词 例如 我们有描述五金店产品的文档 name Torx drive T9 category
  • 字符串搜索算法

    对于两种字符串搜索算法 KMP和后缀树 在什么情况下优选哪种 举一些实际的例子 如果您必须回答很多查询 例如 大海捞针是否存在 则后缀树会更好 如果您只需在另一个字符串中搜索一个字符串 而不需要执行很多次 那么 KMP 会更好 后缀树是一种
  • SwiftUI - 将 SceneKit 场景添加到 MacOS 项目

    目标 使用 UIViewRepresentable 将 SceneKit 场景添加到 SwiftUI MacOS 项目 不是 Catalyst 我做了什么 当目标是 SwiftUI iOS 时 以下代码可以正常工作 但是当目标是 MacOS
  • Node教程一对多无加载远程服务器Stream Spinner动不停

    我对在项目中使用所需的 Kurrento 很陌生 但是当我克隆 git hub 上为 Kurento 提供的教程并遵循 one2Many 调用的说明时 首先 adapter js 的软件包损坏了 因为我成功解决了它们 但之后出现了一个问题
  • 在 turfjs 中创建多个多边形的联合的最快方法是什么?

    我有这样的东西 但对于大集合来说 速度非常慢 let unionize triangles gt if triangles length 0 return null let ret triangles 0 feature triangles
  • Func<> 获取参数信息

    如何获取传入参数的值Func lt gt C 中的 Lambda IEnumerable
  • 如何将 OData 键值添加到我的实体框架类?

    我正在使用 MVC 5 Microsoft OData 2 1 和 Entity Framework 6 我尝试使用我使用 EntitySetController 类编写的 OData 源 当我添加服务引用并使用 OData 元数据时 它可
  • Maven 货物部署到 war 文件无法作为 teamcity 的一部分部署

    相同的部署在 Windows 和 Linux 上可以正常工作 但使用 teamcity 及其内置 Maven 时出现错误 本地部署 报错 容器配置目录 BuildAgent work 68d4a71c8dc5cfd9 target carg
  • 哪些脚本会进入 Python 包的 bin 文件夹?

    我正在从 Learn Python the Hard Way 及其中提到的练习之一中学习 Python 包 在bin目录下放置一个可以运行的脚本 对我来说 这似乎有点模糊 我不太确定 bin 文件夹中会包含什么样的脚本 搭便车者的包装指南
  • 将按钮放在 div 或屏幕底部

    我想将按钮放置在 div 底部或屏幕底部 但处于非固定位置 我的代码结构如下所示 div 1 div 2 div 3 button 我想将按钮放在div 1的底部 其高度是使用jQuery设置的 高度是屏幕的高度 所以将按钮放在屏幕的底部也
  • JavaFX访问内部webkit文档

    我正在尝试访问javafx web com sun webkit dom来自我的未命名模块 javafx 项目 为此 我创建了一个类com sun webkit dom DomMapper 我在 IDE 中没有看到任何错误 但是当我使用mv
  • 如何使用 CDH4 和 Yarn 查看 Hadoop 作业历史记录和日志?

    我使用 Yarn 下载了 Hadoop 的 CDH4 tar 作业运行良好 但我不知道在哪里查看作业日志 在 MRv1 中 我只需访问 JobTracker Web 应用程序 它就有工作历史记录 也可以从这里访问各个作业的日志 或者转到lo
  • R:用升序填充 NA 值

    With R我想用升序 降序数字 整数 填充一列大部分为 NA 值的列 但相对于值为 0 的行 编号应按主题 第一列 分组 这听起来很混乱 所以请看这个例子 数据如下所示 Column 3 是当前数据 Column 4 是目标数据 Subj
  • 使用dispatch_async在Swift中并发分析数组

    我正在尝试使用 GCD 的后台线程同时分析照片 这是我写的代码 dispatch async dispatch get global queue Int QOS CLASS UTILITY value 0 for var i 0 i lt