使用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中并发分析数组 的相关文章

  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • 线程睡眠和Windows服务

    我正在开发一个 Windows 服务 该服务存在一些问题Thread Sleep 所以我想我会尝试使用计时器 因为这个问题建议 在 Windows 服务中使用 Thread Sleep https stackoverflow com que
  • init 中的 Swift 通用约束

    我有通用的 我希望能够用特定的约束来初始化它 约束仅用于初始化 班里的其他人并不关心 这是一个简化的示例 struct Generic
  • RemoteIO 音频单元播放回调中的 AudioBufferList 内容

    我想 拦截 音频数据传送到 iOS 设备扬声器的过程 我相信这可以使用 RemoteIO 音频单元和回调来完成 在下面的playbackCallback中 ioData实际上包含任何音频数据吗 static OSStatus playbac
  • 在视图控制器之间传递数据使用从嵌入导航控制器的视图到 tabbarcontroller 的 Segue

    我有两个视图 我想将数据从一个视图传递到下一个视图 第一个视图是我想要传递给下一个视图的数据的地方 我们称之为SourceViewController 然而SourceViewController嵌入在一个NavigationViewCon
  • 使用 UISearchBar 过滤数组

    我目前正在使用以下代码来过滤数组并将结果显示在我的 tableView 中 问题是 只有当搜索与确切的单词匹配时 才会返回结果 如何更改数组过滤器以在输入时搜索每个字符 let data Mango Grape Berry Orange A
  • ui 测试 xcode,如何使用 cellquery 点击表视图单元格按钮

    我目前正在为我的应用程序进行 ui 测试 并一直点击我的应用程序的登录按钮 我无法找到我提供了标识符注册按钮的元素 该元素是索引中的第三个 这不是问题 let cellQuery self app tables cells element
  • Xcode 存档上传失败并出现错误

    我正在尝试从 xCode 将新版本上传到 iTunesConnect 但每次我都会遇到此问题 问题是什么 我该如何解决这个问题 最近 我开始在上传过程中遇到问题 Xcode 经常卡住 最终会因您看到的第二个错误而失败 受够了一段时间后 我转
  • 如果我的消耗性 IAP 被退款,我会收到任何通知吗?

    我有 Apple iOS 应用程序 其中有很多消耗性 IAP 我非常担心用户购买IAP并使用一段时间后向Apple客服投诉并获得退款 如果我的消耗品 IAP 退款 我会收到任何通知吗 我如何注意到这一点并阻止用户使用 IAP None
  • 相当于 Interface Builder 中 UIButton 的动态类型“自动调整字体”设置?

    UILabel 有一个Dynamic Type Automatically Adjusts FontInterface Builder 属性检查器中的复选框 Interface Builder 中是否有等效项用于自动调整 UIButton
  • Objective-C中如何使继承的类能够看到父类的隐藏方法[重复]

    这个问题在这里已经有答案了 我有两个类 Class1 和 Class2 第二个类继承自第一个类 我需要重写 Class1 的 update 方法来实现我的目标 继承方法中 update方法的改变是在代码中间进行的 所以我不能使用 超级更新
  • 如何使用MKMapView完成加载委托,可能的“完成显示”委托?

    当用户在选择注释后点击 保存 时 我尝试保存地图视图的缩略图 当用户尚未放大该注释时会出现问题 因此尚未加载关闭缩放级别 这就是用户点击保存后我正在做的事情 将布尔值 saving 设置为 true 居中并放大注释 无动画 当调用mapVi
  • 如何在 Xcode 4 中在 .h 和 .m 之间切换

    刚刚安装的 Xcode 4 到目前为止一切顺利 除了 Apple 更改了所有键盘快捷键 有人知道如何在 h 和 m 之间切换吗 苹果改变了各种快捷键 但要在标头和实现之间切换 新的快捷键是 You can change it back to
  • Swift 闭包作为 AnyObject

    我尝试使用这个方法 class addMethod 在 Obj c 中使用如下 class addMethod self class selector eventHandler imp implementationWithBlock han
  • 两者都实现了类。将使用两者之一

    我有一个项目 它具有使用 SocketRocket 的依赖项 通过 CocoaPods 安装 并从 HeapAnalytics 导入了静态库 显然 HeapAnalytics 库已经使用了 SocketRocket 编译时没有出现错误 但在
  • 如何在 ios 7 上更改重新排序控制图像

    我正在寻找一种更改重新排序控件图像和大小的方法 我使用此代码来更改重新排序图像 void tableView UITableView tableView willDisplayCell UITableViewCell cell forRow
  • 如何在 UICollectionView 的节标题中动态添加标签和按钮?

    请帮助我如何水平添加标签和水平添加类似的按钮 但每个按钮应像另一个部分一样在每个标签的下方对齐 这应该在 UICollectionView 的标题中动态发生 因为标签和按钮的数量根据我的数据 我想制作一种 Excel 类型的布局 并在标题中
  • Swift 使用哪种通用排序算法?它在排序数据上表现不佳

    我一直在挑选和探索 Swift 标准库sort 其函数为Array类型 令我惊讶的是 我注意到它在已经排序的数据上表现不佳 对数组进行排序Int打乱顺序似乎比对已经排序的同一个数组进行排序快 5 倍 对已打乱顺序的对象数组进行排序比对已按排
  • 在 iOS 11 中创建 Gif 图像颜色贴图

    最近 我在创建 Gif 时遇到了一个问题 如果它太大 颜色就会丢失 然而 感谢 SO 的帮助 有人能够帮助我找到解决方法并创建我自己的颜色图 上一个问题在这里 保存动画 Gif 时 iOS 颜色不正确 https stackoverflow
  • 使 Guid 属性成为线程安全的

    我的一个类有一个 Guid 类型的属性 该属性可以由多个线程同时读写 我的印象是对 Guid 的读取和写入不是原子的 因此我应该锁定它们 我选择这样做 public Guid TestKey get lock testKeyLock ret

随机推荐

  • 如何使用 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