У меня есть большой массив, который я хотел бы обработать, передав его в несколько асинхронных задач. В качестве доказательства концепции я написал следующий код:
class TestParallelArrayProcessing {
let array: [Int]
var summary: [Int]
init() {
array = Array<Int>(count: 500000, repeatedValue: 0)
for i in 0 ..< 500000 {
array[i] = Int(arc4random_uniform(10))
}
summary = Array<Int>(count: 10, repeatedValue: 0)
}
func calcSummary() {
let group = dispatch_group_create()
let queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)
for i in 0 ..< 10 {
dispatch_group_async(group, queue, {
let base = i * 50000
for x in base ..< base + 50000 {
self.summary[i] += self.array[x]
}
})
}
dispatch_group_notify(group, queue, {
println(self.summary)
})
}
}
После init()
, array
будет инициализирован случайными целыми числами от 0 до 9.
Функция calcSummary
отправляет 10 задач, которые занимают непересекающиеся фрагменты из 50000 элементов из array
и добавляют их, используя их соответствующий интервал в summary
как ускоритель.
Эта программа выходит из строя в строке self.summary[i] += self.array[x]
. Ошибка:
EXC_BAD_INSTRUCTION (code = EXC_I386_INVOP).
Я могу видеть в отладчике, что ему удалось выполнить итерацию несколько раз перед сбоем и что переменные во время сбоя имеют значения в правильных пределах.
Я прочитал, что EXC_I386_INVOP
может произойти при попытке получить доступ к уже выпущенному объекту. Интересно, имеет ли это отношение к Swift, делая копию массива, если он изменен, и если да, то как этого избежать.