public IEnumerable<SparseTwinIndex<float>> Distribute(IEnumerable<SparseArray<float>> productions, IEnumerable<SparseArray<float>> attractions, IEnumerable<IDemographicCategory> cat) { var productionEnum = productions.GetEnumerator(); var attractionEnum = attractions.GetEnumerator(); var catEnum = cat.GetEnumerator(); var numberOfZones = this.Root.ZoneSystem.ZoneArray.GetFlatData().Length; using ( MultiRunGPUGravityModel multiDist = new MultiRunGPUGravityModel( numberOfZones, ( (p) => this.Progress = p ), this.Epsilon, this.MaxIterations ) ) { var zoneArray = this.Root.ZoneSystem.ZoneArray; float[] friction = null; while ( productionEnum.MoveNext() && attractionEnum.MoveNext() && catEnum.MoveNext() ) { yield return multiDist.ProcessFlow( ( friction = this.ComputeFriction( zoneArray.GetFlatData(), catEnum.Current, friction ) ), productionEnum.Current, attractionEnum.Current ); } friction = null; } }
private IEnumerable<SparseTwinIndex<float>> GPUDoublyConstrained(IZone[] zones, IEnumerator<SparseArray<float>> ep, IEnumerator<SparseArray<float>> ea, IEnumerator<IDemographicCategory> ec) { using ( MultiRunGPUGravityModel gm = new MultiRunGPUGravityModel( zones.Length, ( p => this.Progress = p ), this.Epsilon, this.MaxIterations ) ) { float[] friction = null; while ( ep.MoveNext() && ea.MoveNext() && ec.MoveNext() ) { var production = ep.Current; var attraction = ea.Current; var cat = ec.Current; var ret = production.CreateSquareTwinArray<float>(); friction = this.ComputeFriction( zones, cat, production.GetFlatData(), attraction.GetFlatData(), friction ); yield return gm.ProcessFlow( friction, production, attraction ); } } }
private void InitializeFlows() { this.Progress = 0; // we are going to need to split based on this information this.ZoneArray = this.Root.ZoneSystem.ZoneArray; var occupations = this.Root.Demographics.OccupationCategories; var validZones = this.ZoneArray.ValidIndexies().ToArray(); var numberOfZones = validZones.Length; //[Occupation][O , D] var distribution = occupations.CreateSimilarArray<SparseTwinIndex<float>>(); //Generate the place of work place of residence OD's SparseArray<float> O = this.ZoneArray.CreateSimilarArray<float>(); SparseArray<float> D = this.ZoneArray.CreateSimilarArray<float>(); var occupationIndexes = occupations.ValidIndexies().ToArray(); var numCat = Categories.Count; // Start burning that CPU Thread.CurrentThread.Priority = ThreadPriority.Highest; SparseTwinIndex<float> workplaceDistribution = null; SparseTwinIndex<float> prevWorkplaceDistribution = null; float[] friction = null; float[] nextFriction = null; MultiRunGPUGravityModel multiRunGPU = null; for ( int i = 0; i < numCat; i++ ) { this.CurrentOccupationIndex = i; Task assignToPopulation = null; if ( i > 0 ) { assignToPopulation = new Task( delegate() { if ( prevWorkplaceDistribution != null ) { // We actually are assigning to the previous category with this data so we need i - 1 AssignToWorkers( prevWorkplaceDistribution, this.Categories[i - 1] ); prevWorkplaceDistribution = null; } } ); assignToPopulation.Start(); } Task computeNextFriction = null; if ( i + 1 < numCat ) { computeNextFriction = new Task( delegate() { nextFriction = this.ComputeFriction( ZoneArray.GetFlatData(), this.Categories[i + 1], nextFriction ); } ); computeNextFriction.Start(); } this.Categories[i].Generate( O, D ); if ( this.UseGPU ) { if ( i == 0 ) { try { Parallel.Invoke( () => friction = this.ComputeFriction( ZoneArray.GetFlatData(), this.Categories[i], friction ), () => multiRunGPU = new MultiRunGPUGravityModel( O.GetFlatData().Length, ( progress => this.Progress = ( progress / numCat ) + ( (float)i / numCat ) ), this.Epsilon, this.MaxIterations ) ); } catch ( AggregateException e ) { throw new XTMFRuntimeException( e.InnerException.Message + "\r\n" + e.InnerException.StackTrace ); } } workplaceDistribution = multiRunGPU.ProcessFlow( friction, O, D ); } else { GravityModel gravityModel = new GravityModel( ImpedenceFunction, ( progress => this.Progress = ( progress / numCat ) + ( (float)i / numCat ) ), this.Epsilon, this.MaxIterations ); workplaceDistribution = gravityModel.ProcessFlow( O, D, validZones ); } this.Progress = ( (float)( i + 1 ) / numCat ); if ( assignToPopulation != null ) { try { assignToPopulation.Wait(); assignToPopulation.Dispose(); assignToPopulation = null; } catch ( AggregateException e ) { throw new XTMFRuntimeException( e.InnerException.Message + "\r\n" + e.InnerException.StackTrace ); } } if ( computeNextFriction != null ) { try { computeNextFriction.Wait(); computeNextFriction.Dispose(); computeNextFriction = null; } catch ( AggregateException e ) { throw new XTMFRuntimeException( e.InnerException.Message + "\r\n" + e.InnerException.StackTrace ); } } prevWorkplaceDistribution = workplaceDistribution; var frictionTemp = friction; friction = nextFriction; nextFriction = friction; } friction = null; nextFriction = null; prevWorkplaceDistribution = null; if ( multiRunGPU != null ) { multiRunGPU.Dispose(); multiRunGPU = null; } AssignToWorkers( workplaceDistribution, this.Categories[numCat - 1] ); workplaceDistribution = null; // ok now we can relax Thread.CurrentThread.Priority = ThreadPriority.Normal; GC.Collect(); }