Swy性能中的xy数组

时间:2017-08-04 14:53:43

标签: arrays swift swift-playground

我有两个带浮点数的大(数千个值)数组,并希望将它们组合在一个xy点数组中以便进一步处理,例如绘制。

现在,在Xcode游乐场,我正在这样做:

let xArray = // read from datafile, fast
let yArray = // read from another datafile, fast

struct xyPoint {
   let x: Float
   let y: Float
}

var spectrum: [xyPoint] = []

for i in 0..<xArray.count {
    let xy = xyPoint(x: xArray[i], y: yArray[i])
    spectrum.append(xy)
}

现在,当我在操场上跑步时,这需要很长时间。

我有什么想法可以加快速度吗?

4 个答案:

答案 0 :(得分:3)

创建点数组的最简单方法是

let spectrum = zip(xArray, yArray).map(XYPoint.init)

(我冒昧地将结构XYPoint称为Swift类型 应该以大写字母开头。)这也允许定义 结果数组为常量。

然而,就执行时间而言,它并不是最快的。 原因可能是

  • zip()对一般序列进行操作,但不利用 输入是数组。
  • zip()返回Sequence,因此map() 不知道要创建的元素的数量。 因此,目标阵列将重新分配几个 次。

因此,如果您保留所需的显式循环,则更快 提前容量:

var spectrum: [XYPoint] = []
spectrum.reserveCapacity(xArray.count)
for i in 0..<xArray.count {
    let xy = XYPoint(x: xArray[i], y: yArray[i])
    spectrum.append(xy)
}

在我的测试中(在1.2 GHz Intel Core m5 MacBook上,在Release中编译) 模式)有两个10,000个元素的数组,第一个方法 大约0.65毫秒,第二种方法大约0.42毫秒。 对于1,000,000个元素,我测量了12毫秒而不是6毫秒。

答案 1 :(得分:2)

一旦你有两个独立的阵列,将它们组合起来有点尴尬,并且没有一个整洁的“Swifty”方法来做到这一点。如果你有一个结构数组,其中每个结构包含一个x和y值,你可以使用map语句将该数组转换为一个CGPoint对象数组(实际上是另一个结构类型)。

你首先告诉我们:

let xArray = // read from datafile, fast
let yArray = // read from another datafile, fast

重做那些你没有显示的代码可能会更好,这样你就不用读取所有的x点数据文件,而是读取所有的y点数据文件:

  • 读取x点
  • 读取y点
  • 为该X / Y对创建一个CGPoint
  • 将新CGPoint添加到CGPoint
  • 的输出数组中

甚至,重构您创建数据文件的代码,以便它写入包含X / Y对数组的文件,而不是2个单独的文件。

如果你有两个独立的数组,你可以使用for ... in的变体为你提供索引和每个数组条目的值:

let xArray: [CGFloat] = [0.1, 0.2, 0.3, 0.4]
let yArray: [CGFloat] = [0.4, 0.3, 0.2, 0.1]

var output = [CGPoint]()
output.reserveCapacity(xArray.count)
for (index, value) in xArray.enumerated() {
    let yValue = yArray[index]
    let aPoint = CGPoint (x: value, y: yValue)
    output.append(aPoint)
}

如果yArray的值低于xArray,则上述代码会崩溃,如果yArray包含更多值,则会遗漏xArray中的最后一个值{1}}。完整的实现应该首先进行错误检查,并处理数据具有不同数量值的情况。

答案 2 :(得分:2)

我检查了您的问题的各种解决方案的性能。您可以从this link to github

下载我的测试

A)您的代码

var spectrum: [XYPoint] = []
for i in 0..<xArray.count {
    let xy = XYPoint(x: xArray[i], y: yArray[i])
    spectrum.append(xy)
}

B)Zip + map(Martin R's answer

let spectrumB = zip(xArray, yArray).map(XYPoint.init)

C)范围+地图(我的解决方案)

let spectrum = (0 ..< xArray.count).map { i in
    return XYPoint(x: xArray[i], y: yArray[i])
}

D)ReserveCapacity + append(Duncan C's answer

var spectrum: [XYPoint] = []
spectrum.reserveCapacity(xArray.count)
for (index, value) in xArray.enumerated() {
    spectrum.append(XYPoint(x: xArray[index], y: yArray[index]))
}

我的结果(以秒为单位)

            ╭──────────────┬──────────────┬──────────────┬──────────────╮
            │       A      │       B      │       C      │       D      │
╭───────────╬══════════════╪══════════════╪══════════════╪══════════════╡
│       100 ║  0.000009426 │  0.000002401 │  0.000000571 │  0.000000550 │
│       200 ║  0.000003356 │  0.000002629 │  0.000000911 │  0.000000866 │
│       500 ║  0.000005610 │  0.000007288 │  0.000002236 │  0.000002012 │
│      1000 ║  0.000010638 │  0.000009181 │  0.000003905 │  0.000005030 │
│      2000 ║  0.000019377 │  0.000013316 │  0.000007116 │  0.000008732 │
│      5000 ║  0.000023430 │  0.000019304 │  0.000019809 │  0.000019092 │
│     10000 ║  0.000050463 │  0.000031669 │  0.000035121 │  0.000035420 │
│     20000 ║  0.000087040 │  0.000058664 │  0.000069300 │  0.000069456 │
│     50000 ║  0.000272357 │  0.000204213 │  0.000176962 │  0.000192996 │
│    100000 ║  0.000721436 │  0.000459551 │  0.000415024 │  0.000437604 │
│    200000 ║  0.001114534 │  0.000924621 │  0.000816374 │  0.000896202 │
│    500000 ║  0.002576687 │  0.002094998 │  0.001860833 │  0.002060462 │
│   1000000 ║  0.007063596 │  0.005924892 │  0.004319181 │  0.004869024 │
│   2000000 ║  0.014474969 │  0.013594134 │  0.008568550 │  0.009388957 │
│   5000000 ║  0.038348767 │  0.035136008 │  0.021276415 │  0.023855382 │
│  10000000 ║  0.081750925 │  0.078742713 │  0.043578664 │  0.047700495 │
│  20000000 ║  0.202616669 │  0.199960563 │  0.148141266 │  0.145360923 │
│  50000000 ║  0.567078563 │  0.552158644 │  0.370327555 │  0.397115294 │
│ 100000000 ║  1.136993625 │  1.101725386 │  0.713406642 │  0.740150322 │
└───────────╨──────────────┴──────────────┴──────────────┴──────────────┘

答案 3 :(得分:1)

当您在主操场文件中运行代码时,您可能已启用日志记录。这为代码增加了巨大的性能。

我在问题中尝试了你的代码作为一个函数。将函数放在主swift文件中,大小为10000的数组需要10分钟!

我将该函数移动到操场的sources文件夹中具有相同大小数组的单独swift文件,并立即完成。

我使用的代码来自您的问题(在func中),而不是优化版本。

相关问题