Having the ability to run duties in parallel is good, it may well velocity up issues for certain when you’ll be able to make the most of a number of CPU cores, however how can we really implement these sort of operations in Swift? 🤔

There are a number of methods of operating parallel operations, I had an extended article in regards to the Grand Central Dispatch (GCD) framework, there I defined the variations between parallelism and concurrency. I additionally demonstrated methods to arrange serial and concurrent dispatch queues, however this time I might prefer to focus a bit extra on duties, employees and jobs.

Think about that you’ve an image which is 50000 pixel vast and 20000 pixel lengthy, that is precisely one billion pixels. How would you alter the colour of every pixel? Nicely, we may do that by iterating by means of every pixel and let one core do the job, or we may run duties in parallel.

The Dispatch framework provides a number of methods to unravel this subject. The primary resolution is to make use of the concurrentPerform operate and specify some variety of employees. For the sake of simplicity, I’ll add up the numbers from zero to 1 billion utilizing 8 employees. 💪

```
import Dispatch
let employees: Int = 8
let numbers: [Int] = Array(repeating: 1, rely: 1_000_000_000)
var sum = 0
DispatchQueue.concurrentPerform(iterations: employees) { index in
let begin = index * numbers.rely / employees
let finish = (index + 1) * numbers.rely / employees
print("Employee #(index), objects: (numbers[start..<end].rely)")
sum += numbers[start..<end].scale back(0, +)
}
print("Sum: (sum)")
```

Cool, however nonetheless every employee has to work on various numbers, perhaps we should not begin all the employees directly, however use a pool and run solely a subset of them at a time. That is fairly a straightforward activity with operation queues, let me present you a fundamental instance. 😎

```
import Basis
let employees: Int = 8
let numbers: [Int] = Array(repeating: 1, rely: 1_000_000_000)
let operationQueue = OperationQueue()
operationQueue.maxConcurrentOperationCount = 4
var sum = 0
for index in 0..<employees {
let operation = BlockOperation {
let begin = index * numbers.rely / employees
let finish = (index + 1) * numbers.rely / employees
print("Employee #(index), objects: (numbers[start..<end].rely)")
sum += numbers[start..<end].scale back(0, +)
}
operationQueue.addOperation(operation)
}
operationQueue.waitUntilAllOperationsAreFinished()
print("Sum: (sum)")
```

Each of the examples are above are extra ore much less good to go (if we glance by means of at potential information race & synchronization), however they depend upon further frameworks. In different phrases they’re non-native Swift options. What if we may do one thing higher utilizing structured concurrency?

```
let employees: Int = 8
let numbers: [Int] = Array(repeating: 1, rely: 1_000_000_000)
let sum = await withTaskGroup(of: Int.self) { group in
for i in 0..<employees {
group.addTask {
let begin = i * numbers.rely / employees
let finish = (i + 1) * numbers.rely / employees
return numbers[start..<end].scale back(0, +)
}
}
var abstract = 0
for await consequence in group {
abstract += consequence
}
return abstract
}
print("Sum: (sum)")
```

By utilizing activity teams you’ll be able to simply setup the employees and run them in parallel by including a activity to the group. Then you’ll be able to look forward to the partial sum outcomes to reach and sum every part up utilizing a thread-safe resolution. This strategy is nice, however is it potential to restrict the utmost variety of concurrent operations, similar to we did with operation queues? 🤷♂️

```
func parallelTasks<T>(
iterations: Int,
concurrency: Int,
block: @escaping ((Int) async throws -> T)
) async throws -> [T] {
attempt await withThrowingTaskGroup(of: T.self) { group in
var consequence: [T] = []
for i in 0..<iterations {
if i >= concurrency {
if let res = attempt await group.subsequent() {
consequence.append(res)
}
}
group.addTask {
attempt await block(i)
}
}
for attempt await res in group {
consequence.append(res)
}
return consequence
}
}
let employees: Int = 8
let numbers: [Int] = Array(repeating: 1, rely: 1_000_000_000)
let res = attempt await parallelTasks(
iterations: employees,
concurrency: 4
) { i in
print(i)
let begin = i * numbers.rely / employees
let finish = (i + 1) * numbers.rely / employees
return numbers[start..<end].scale back(0, +)
}
print("Sum: (res.scale back(0, +))")
```

It’s potential, I made a bit helper operate just like the `concurrentPerform`

methodology, this fashion you’ll be able to execute a lot of duties and restrict the extent of concurrency. The primary concept is to run a lot of iterations and when the index reaches the utmost variety of concurrent objects you wait till a piece merchandise finishes and then you definately add a brand new activity to the group. Earlier than you end the duty you additionally need to await all of the remaining outcomes and append these outcomes to the grouped consequence array. 😊

That is it for now, I hope this little article will show you how to to handle concurrent operations a bit higher.