Arrays 在Swift中并发访问数组元素

Arrays 在Swift中并发访问数组元素,arrays,swift,concurrency,objective-c++,Arrays,Swift,Concurrency,Objective C++,我尝试以Swift并发方式从数组(不同的数组)写入和读取,但在运行时的写入操作中出现异常。 我有Objective-C++中的并发模糊代码: - (cpp_blur::Bitmap)blur { Bitmap result(_source); auto indexes = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, _source.size())]; int minIndex = 0; int

我尝试以Swift并发方式从数组(不同的数组)写入和读取,但在运行时的写入操作中出现异常。 我有Objective-C++中的并发模糊代码:

- (cpp_blur::Bitmap)blur {
    Bitmap result(_source);
    auto indexes = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, _source.size())];
    int minIndex = 0;
    int maxIndex = static_cast<int>(result.size()) - 1;
    [indexes enumerateIndexesWithOptions:NSEnumerationConcurrent
                              usingBlock:[&](NSUInteger idx, BOOL* _Nonnull stop){
        double sum = 0.0;
        for (int i = static_cast<int>(idx) - static_cast<int>(self.radius); i <= idx + self.radius; i++) {
            int index = clamp(i, minIndex, maxIndex);
            sum += self->_source.at(index);
        }
        sum /= static_cast<double>(self.radius * 2 + 1);
        result.at(idx) = sum;
    }];

    return result;
}
如果我在
result[index]=avg
周围添加一个锁,这个异常将被移除,但我会遇到性能问题。 如何在不锁定的情况下更改Swift数组中元素的值(同时只更改不同的元素)?

这是否回答了您的问题?不,等待完成所有任务不是有问题吗。但在答案中,还添加了一个围绕书写操作的锁。我想避免锁,因为我写入不同的索引,并且有足够的内存。锁的存在是为了防止在数组中写入时出现竞速情况。不管你有没有资源,你都希望这样。考虑到
等待完成
枚举索引选项
内置了它。无需等待,外部函数将只返回
结果的初始值
。您必须等待同步写入内容。此外,所有语言中大多数集合类型的实现在写入时都不是线程安全的。您永远不应该假设它“就像在不同的线程中更改不同的变量”。除非你喜欢花几个晚上调试崩溃的并行代码。如果你特别询问
Blur
:它应该在
CPU
上完成。如果你问的是一般性问题:为了获得理想的性能,你必须使用缓冲区等手动管理内存。但最好看看
simd
@objc public func blur() -> [Double] {
        var result = source
        let indexSet = NSIndexSet(indexesIn: NSMakeRange(0, source.count))
        let from = -Int(self.blurRadius)
        let to = Int(self.blurRadius)
        let lastIndex = self.source.count - 1
        indexSet.enumerate(options: .concurrent) { (index:Int, _) in
            let sum = ((from + index)...(to + index)).reduce(0.0) { (partial:Double, nonClamped:Int) -> Double in
                let index = self.clamp(nonClamped, min: 0, max: lastIndex)
                let result = partial + self.source[index]
                return result
            }
            let avg = sum / Double(2 * self.blurRadius + 1);
            result[index] = avg //here I have crash in runtime
        }

        return result
    }