是否可以在 enumerateObjects(options: .concurrent) 中填充字典或数组?尝试填充字典时,我继续收到 EXC_BAD_ACCESS 错误。当我添加信号量时它会起作用,但是在字典前面添加信号量也会增加大量开销,并且违背了我想要使用 enumerateObjects(options: .concurrent) 来提高性能的整个目的。 这是我目前拥有的代码:
func parseImgColor(_ cgImage: CGImage){
let yRange = (0..<cgImage.height)
let yArray: NSArray = yRange.map { $0 } as NSArray
let xRange = (0..<cgImage.width)
let xArray: NSArray = xRange.map { $0 } as NSArray
var coordinateMap: [Coordinate : CoordColor] = [:]
yArray.enumerateObjects(options: .concurrent) { yPosition, index, yStopPointer in
guard let y: Int = yPosition as? Int else {
yStopPointer.pointee = true
return
}
xArray.enumerateObjects(options: .concurrent) { xPosition, index, xStopPointer in
guard let x: Int = xPosition as? Int else {
xStopPointer.pointee = true
return
}
let coords = Coordinate(x: x, y: y)
if x % 2 == 0{
coordinateMap[coords] = CoordColor(value: UIColor.blue);
} else {
coordinateMap[coords] = CoordColor(value: UIColor.white);
}
}
}
}
我用来定义字典的结构包括:
struct Coordinate: Hashable {
let x: Int
let y: Int
}
struct CoordColor: Hashable{
let value: UIColor
}
如果繁重的计算发生在循环内部,那么也许在串行队列上收集结果不会那么糟糕。
另外,为什么不将两个 (x,y) 范围压缩在一起,然后使用类似
DispatchQueue.concurrentPerform()
的东西来并行化计算,而不是使用每个在并发队列上生成的两个嵌套循环?
所以这就是我会尝试做的:
// Image size
let width = 3
let height = 4
// Total number of iterations
let iterationCount = width * height
// Your dictionary key
struct Coordinate: Hashable, CustomDebugStringConvertible {
var x: Int
var y: Int
var debugDescription: String {
return "\(x).\(y)"
}
}
// Spawn on concurrent queue
DispatchQueue.global().async {
var result: [Coordinate: String] = [:]
let resultQueue = DispatchQueue(label: "ResultCollectorQueue")
DispatchQueue.concurrentPerform(iterations: iterationCount) { i in
// Compute x,y for the image, however you could also zip xArray and yArray ranges together instead
let x = i / width
let y = i % width
// Do something heavy
// Collect the result on a serial queue
resultQueue.async {
result[Coordinate(x: x, y: y)] = "\(x) \(y)"
}
}
// Pick up the result
resultQueue.async {
print("Got result: \(result)")
}
}
objc.io 上有一份很棒的材料,深入探讨了并发映射的实现:https://talk.objc.io/episodes/S01E90-concurrent-map
修改时可以锁定/解锁。
private static let locker = NSLock()
locker.lock()
...
...modify
...
locker.unlock()