public override GroupByResults Group(ITableResults resTable) { // Create hashers and equality comparers. // The hashers receive also the equality comparer as cache. CreateHashersAndComparers(out ExpressionComparer[] comparers, out ExpressionHasher[] hashers); return(this.ParallelGroupBy(RowEqualityComparerInt.Factory(resTable, comparers, new RowHasher(hashers), false), resTable)); }
protected override GroupByJob[] CreateSpecJobs(GroupByJob[] jobs, RowEqualityComparerInt equalityComparer, ITableResults resTable, int current, int addition) { var concurrentDictBuckets = new ConcurrentDictionary <int, AggregateBucketResult[]>(equalityComparer); for (int i = 0; i < jobs.Length - 1; i++) { jobs[i] = new GroupByJobBuckets(concurrentDictBuckets, this.aggregates, resTable, current, current + addition); current += addition; } jobs[jobs.Length - 1] = new GroupByJobBuckets(concurrentDictBuckets, this.aggregates, resTable, current, resTable.NumberOfMatchedElements); return(jobs); }
/// <summary> /// Creates jobs for the parallel group by. /// Note that the last job in the array has the end set to the end of the result table. /// Each job will receive a range from result table, aggregates and a global place to store groups and the aggregated values. /// Note that there is a single comparer for the ConcurrentDictionary, thus no caching of the expression is done. /// </summary> private GroupByJob[] CreateJobs(RowEqualityComparerInt equalityComparer, ITableResults resTable) { GroupByJob[] jobs = new GroupByJob[this.ThreadCount]; int current = 0; int addition = resTable.NumberOfMatchedElements / this.ThreadCount; if (addition == 0) { throw new ArgumentException($"{this.GetType()}, a range for a thread cannot be 0."); } return(CreateSpecJobs(jobs, equalityComparer, resTable, current, addition)); }
protected override GroupByJob[] CreateSpecJobs(GroupByJob[] jobs, RowEqualityComparerInt equalityComparer, ITableResults resTable, int current, int addition) { var aggResults = AggregateArrayResults.CreateArrayResults(this.aggregates); var concurrentDictArrays = new ConcurrentDictionary <int, int>(equalityComparer); int capture = 0; Func <int, int> positionFactory = (int x) => { return(Interlocked.Increment(ref capture)); }; Semaphore semaphore = new Semaphore(this.ThreadCount, this.ThreadCount); for (int i = 0; i < jobs.Length - 1; i++) { jobs[i] = new GroupByJobArrays(concurrentDictArrays, this.aggregates, resTable, current, current + addition, aggResults, positionFactory, semaphore, jobs.Length); current += addition; } jobs[jobs.Length - 1] = new GroupByJobArrays(concurrentDictArrays, this.aggregates, resTable, current, resTable.NumberOfMatchedElements, aggResults, positionFactory, semaphore, jobs.Length); return(jobs); }
private GroupByResults ParallelGroupBy(RowEqualityComparerInt equalityComparer, ITableResults resTable) { var jobs = CreateJobs(equalityComparer, resTable); var tasks = new Task[this.ThreadCount - 1]; for (int i = 0; i < tasks.Length; i++) { var tmp = jobs[i]; tasks[i] = Task.Factory.StartNew(() => SingleThreadGroupByWork(tmp)); } // The main thread works with the last job in the array. SingleThreadGroupByWork(jobs[jobs.Length - 1]); Task.WaitAll(tasks); // No merge needed. return(CreateGroupByResults(jobs[0])); }
protected abstract GroupByJob[] CreateSpecJobs(GroupByJob[] jobs, RowEqualityComparerInt equalityComparer, ITableResults resTable, int current, int addition);