Внутри массива есть указатели, которые могут совершенно измениться у вас под ногами.Это не необработанная память.
Массивы не являются поточно-ориентированными.Массивы являются типами значений, что означает, что они поддерживают копирование при записи потокобезопасным способом (так что вы можете свободно передавать массив в другой поток, и если он там скопирован, это нормально), но вы не можетемутировать один и тот же массив в нескольких потоках.Массив не является C-буфером.Не обещано иметь непрерывную память.Даже не обещали выделять память вообще.Массив может выбрать внутреннее хранение «Я в настоящее время все нули» в качестве особого состояния и просто вернуть 0 для каждого индекса.(Это не так, но разрешено.)
Для этой конкретной проблемы вы обычно используете методы vDSP, такие как vDSP_vramp, но я понимаю, что это всего лишь пример, а метода vDSP может и не бытьэто решает проблему.Однако, как правило, я бы все же сосредоточился на методах Accelerate / SIMD, а не на отправке в очереди.
Но если вы собираетесь отправлять в очереди, вам потребуется UnsafeMutableBuffer для управления памятью (иубедитесь, что память вообще существует):
pixels.withUnsafeMutableBufferPointer { pixelsPtr in
DispatchQueue.concurrentPerform(iterations: threadCount) { thread in
for number in thread*size ..< (thread+1)*size {
let floating = Float(number)
pixelsPtr[number] = SIMD3(floating, floating, floating)
}
}
}
«Небезопасно» означает, что теперь ваша задача - убедиться, что все обращения разрешены, и что вы не создаете условия гонки.
Обратите внимание на использование .concurrentPerform
здесь.Как напоминает нам @ user3441734, pixelsPtr
не обещает быть действительным после завершения .withUnsafeMutablePointer
..concurrentPerform
гарантированно не вернется, пока все блоки не будут завершены, поэтому указатель гарантированно будет действительным.
Это можно сделать и с DispatchGroup, но .wait
должно быть внутри withUnsafeMutableBufferPointer
.