C#如何将带外部对象条件更新的串行for循环改写为并行循环
遗传算法串行循环并行化实现方案
前置注意事项
- 请先确保
DNA<T>.CalculateFitness()方法是线程安全的,方法内部不要修改共享的非线程安全变量,这是并行化生效的前提 - 实现使用.NET内置的
Parallel.For,语法接近传统for循环,不需要复杂LINQ操作
完整并行实现代码
using System.Threading.Tasks; // 代码头部先引入该命名空间 // 初始化全局结果变量,和原串行逻辑一致 double fitnessSum = 0; DNA<T> best = Population[0]; // 线程安全锁对象,用于保护全局变量的更新操作 object lockObj = new object(); Parallel.For(0, Population.Count, // 每个线程的本地状态初始化:每个新线程启动时执行一次,初始化该线程专属的本地累加和、本地最优个体 () => new { LocalSum = 0.0, LocalBest = Population[0] }, // 单次循环迭代的执行逻辑,和原串行逻辑完全一致 (i, loopState, localState) => { double fitnessThisPopulation = Population[i].CalculateFitness(i); // 更新当前线程的本地累加和 double newSum = localState.LocalSum + fitnessThisPopulation; // 更新当前线程的本地最优个体 DNA<T> newBest = Population[i].fitness > localState.LocalBest.fitness ? Population[i] : localState.LocalBest; // 返回更新后的本地状态,供该线程下一次迭代使用 return new { LocalSum = newSum, LocalBest = newBest }; }, // 每个线程执行完成后的结果合并逻辑,将线程本地结果合并到全局变量 localState => { // 加锁保证全局变量更新的线程安全 lock(lockObj) { fitnessSum += localState.LocalSum; if (localState.LocalBest.fitness > best.fitness) { best = localState.LocalBest; } } }); BestFitness = best.fitness;
逻辑说明
Parallel.For的前两个参数和传统for循环完全一致,分别是循环起始值、循环结束值。该实现通过每个线程独立存储本地累加和、本地最优个体的方式,避免了每次迭代都加锁的性能损耗,仅在每个线程全部执行完成后才会加锁合并一次结果,性能开销极低,整体逻辑和你原有的串行逻辑完全对齐。
内容的提问来源于stack exchange,提问作者Fritz45
相关产品推荐
相关产品推荐

