草庐IT

ios - 同步排队比异步排队时代码运行得更快。不应该相反吗?

coder 2023-09-12 原文

我试图通过至少在两个不同的核心上分布它来加速一个减慢我的主线程的进程。

我认为我可以做到这一点的原因是每个单独的操作都是独立的,只需要两个点和一个 float 。

然而,我的第一个尝试是在执行 queue.asncqueue.sync 时代码运行速度明显变慢,我不知道为什么!

这里是同步运行的代码

var block = UnsafeMutablePointer<Datas>.allocate(capacity: 0)
var outblock = UnsafeMutablePointer<Decimal>.allocate(capacity: 0)
func initialise()
{
    outblock = UnsafeMutablePointer<Decimal>.allocate(capacity: testWith * 4 * 2)

    block = UnsafeMutablePointer<Datas>.allocate(capacity: particles.count)
}

func update()
{
    var i = 0
    for part in particles
    {
        part.update()

        let x1 = part.data.p1.x; let y1 = part.data.p1.y
        let x2 = part.data.p2.x; let y2 = part.data.p2.x;

        let w = part.data.size * rectScale
        let w2 = part.data.size * rectScale

        let dy = y2 - y1; let dx = x2 - x1
        let length = sqrt(dy * dy + dx * dx)
        let calcx = (-(y2 - y1) / length)
        let calcy = ((x2 - x1) / length)
        let calcx1 = calcx * w
        let calcy1 = calcy * w
        let calcx2 = calcx * w2
        let calcy2 = calcy * w2
        outblock[i] = x1 + calcx1
        outblock[i+1] = y1 + calcy1

        outblock[i+2] = x1 - calcx1
        outblock[i+3] = y1 - calcy1

        outblock[i+4] = x2 + calcx2
        outblock[i+5] = y2 + calcy2

        outblock[i+6] = x2 - calcx2
        outblock[i+7] = y2 - calcy2

        i += 8
    }
}

这是我在多个内核之间分配工作负载的尝试

let queue = DispatchQueue(label: "construction_worker_1", attributes: .concurrent)

let blocky = block
let oblocky = outblock
for i in 0..<particles.count
{
    particles[i].update()
    block[i] = particles[i].data//Copy the raw data into a thead safe format
    queue.async {
        let x1 = blocky[i].p1.x; let y1 = blocky[i].p1.y
        let x2 = blocky[i].p2.x; let y2 = blocky[i].p2.x;

        let w = blocky[i].size * rectScale
        let w2 = blocky[i].size * rectScale

        let dy = y2 - y1; let dx = x2 - x1
        let length = sqrt(dy * dy + dx * dx)
        let calcx = (-(y2 - y1) / length)
        let calcy = ((x2 - x1) / length)
        let calcx1 = calcx * w
        let calcy1 = calcy * w
        let calcx2 = calcx * w2
        let calcy2 = calcy * w2

        let writeIndex = i * 8
        oblocky[writeIndex] = x1 + calcx1
        oblocky[writeIndex+1] = y1 + calcy1

        oblocky[writeIndex+2] = x1 - calcx1
        oblocky[writeIndex+3] = y1 - calcy1

        oblocky[writeIndex+4] = x2 + calcx2
        oblocky[writeIndex+5] = y2 + calcy2

        oblocky[writeIndex+6] = x2 - calcx2
        oblocky[writeIndex+7] = y2 - calcy2
    }
}

我真的不知道为什么会出现这种放缓!我正在使用 UnsafeMutablePointer,因此数据是线程安全的,并且我确保没有变量可以同时被多个线程读取或写入。

这是怎么回事?

最佳答案

Performing Loop Iterations Concurrently 中所述,将每个 block 分派(dispatch)到某个后台队列都会产生开销。因此,您需要“跨越”数组,让每次迭代处理多个数据点,而不仅仅是一个。

此外,dispatch_apply,在 Swift 3 及更高版本中称为 concurrentPerform,专为并行执行循环而设计,并针对特定设备的内核进行了优化。结合跨步,您应该获得一些性能优势:

DispatchQueue.global(qos: .userInitiated).async {
    let stride = 100
    DispatchQueue.concurrentPerform(iterations: particles.count / stride) { iteration in
        let start = iteration * stride
        let end = min(start + stride, particles.count)
        for i in start ..< end {
            particles[i].update()
            block[i] = particles[i].data//Copy the raw data into a thead safe format
            queue.async {
                let x1 = blocky[i].p1.x; let y1 = blocky[i].p1.y
                let x2 = blocky[i].p2.x; let y2 = blocky[i].p2.x

                let w = blocky[i].size * rectScale
                let w2 = blocky[i].size * rectScale

                let dy = y2 - y1; let dx = x2 - x1
                let length = hypot(dy, dx)
                let calcx = -dy / length
                let calcy = dx / length
                let calcx1 = calcx * w
                let calcy1 = calcy * w
                let calcx2 = calcx * w2
                let calcy2 = calcy * w2

                let writeIndex = i * 8
                oblocky[writeIndex] = x1 + calcx1
                oblocky[writeIndex+1] = y1 + calcy1

                oblocky[writeIndex+2] = x1 - calcx1
                oblocky[writeIndex+3] = y1 - calcy1

                oblocky[writeIndex+4] = x2 + calcx2
                oblocky[writeIndex+5] = y2 + calcy2

                oblocky[writeIndex+6] = x2 - calcx2
                oblocky[writeIndex+7] = y2 - calcy2
            }
        }
    }
}

您应该尝试不同的 stride 值,看看性能如何变化。

我无法运行此代码(我没有示例数据,我没有Datas 的定义等),所以如果我引入任何问题,我深表歉意。但是不要关注这里的代码,而是关注更广泛的问题,即使用 concurrentPerform 执行并发循环,并努力确保每个线程都有足够的工作,因此线程开销并不会超过并行运行线程带来的更广泛的好处。

有关详细信息,请参阅 https://stackoverflow.com/a/22850936/1271826在这里对问题进行更广泛的讨论。

关于ios - 同步排队比异步排队时代码运行得更快。不应该相反吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46498928/

有关ios - 同步排队比异步排队时代码运行得更快。不应该相反吗?的更多相关文章

  1. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  2. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  3. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  4. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  5. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  6. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  7. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  8. ruby-on-rails - 带有 Zeus 的 RSpec 3.1,我应该在 spec_helper 中要求 'rspec/rails' 吗? - 2

    使用rspec-rails3.0+,测试设置分为spec_helper和rails_helper我注意到生成的spec_helper不需要'rspec/rails'。这会导致zeus崩溃:spec_helper.rb:5:in`':undefinedmethod`configure'forRSpec:Module(NoMethodError)对thisissue最常见的回应是需要'rspec/rails'。但这是否会破坏仅使用spec_helper拆分rails规范和PORO规范的全部目的?或者这无关紧要,因为Zeus无论如何都会预加载Rails?我应该在我的spec_helper中做

  9. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  10. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

随机推荐