private void InitializePartitions(IEnumerable <T> source, int partitionCount, bool useStriping) { ParallelEnumerableWrapper <T> wrapper = source as ParallelEnumerableWrapper <T>; if (wrapper != null) { source = wrapper.WrappedEnumerable; } IList <T> data = source as IList <T>; if (data != null) { QueryOperatorEnumerator <T, int>[] enumeratorArray = new QueryOperatorEnumerator <T, int> [partitionCount]; int count = data.Count; T[] localArray = source as T[]; int maxChunkSize = -1; if (useStriping) { maxChunkSize = Scheduling.GetDefaultChunkSize <T>(); if (maxChunkSize < 1) { maxChunkSize = 1; } } for (int i = 0; i < partitionCount; i++) { if (localArray != null) { if (useStriping) { enumeratorArray[i] = new ArrayIndexRangeEnumerator <T>(localArray, partitionCount, i, maxChunkSize); } else { enumeratorArray[i] = new ArrayContiguousIndexRangeEnumerator <T>(localArray, partitionCount, i); } } else if (useStriping) { enumeratorArray[i] = new ListIndexRangeEnumerator <T>(data, partitionCount, i, maxChunkSize); } else { enumeratorArray[i] = new ListContiguousIndexRangeEnumerator <T>(data, partitionCount, i); } } base.m_partitions = enumeratorArray; } else { base.m_partitions = PartitionedDataSource <T> .MakePartitions(source.GetEnumerator(), partitionCount); } }
//--------------------------------------------------------------------------------------- // This method just creates the individual partitions given a data source. // // Notes: // We check whether the data source is an IList<T> and, if so, we can partition // "in place" by calculating a set of indexes. Otherwise, we return an enumerator that // performs partitioning lazily. Depending on which case it is, the enumerator may // contain synchronization (i.e. the latter case), meaning callers may occ----ionally // block when enumerating it. // private void InitializePartitions(IEnumerable <T> source, int partitionCount, bool useStriping) { Contract.Assert(source != null); Contract.Assert(partitionCount > 0); // If this is a wrapper, grab the internal wrapped data source so we can uncover its real type. ParallelEnumerableWrapper <T> wrapper = source as ParallelEnumerableWrapper <T>; if (wrapper != null) { source = wrapper.WrappedEnumerable; Contract.Assert(source != null); } // Check whether we have an indexable data source. IList <T> sourceAsList = source as IList <T>; if (sourceAsList != null) { QueryOperatorEnumerator <T, int>[] partitions = new QueryOperatorEnumerator <T, int> [partitionCount]; int listCount = sourceAsList.Count; // We use this below to specialize enumerators when possible. T[] sourceAsArray = source as T[]; // If range partitioning is used, chunk size will be unlimited, i.e. -1. int maxChunkSize = -1; if (useStriping) { maxChunkSize = Scheduling.GetDefaultChunkSize <T>(); // The minimum chunk size is 1. if (maxChunkSize < 1) { maxChunkSize = 1; } } // Calculate indexes and construct enumerators that walk a subset of the input. for (int i = 0; i < partitionCount; i++) { if (sourceAsArray != null) { // If the source is an array, we can use a fast path below to index using // 'ldelem' instructions rather than making interface method calls. if (useStriping) { partitions[i] = new ArrayIndexRangeEnumerator(sourceAsArray, partitionCount, i, maxChunkSize); } else { partitions[i] = new ArrayContiguousIndexRangeEnumerator(sourceAsArray, partitionCount, i); } TraceHelpers.TraceInfo("ContigousRangePartitionExchangeStream::MakePartitions - (array) #{0} {1}", i, maxChunkSize); } else { // Create a general purpose list enumerator object. if (useStriping) { partitions[i] = new ListIndexRangeEnumerator(sourceAsList, partitionCount, i, maxChunkSize); } else { partitions[i] = new ListContiguousIndexRangeEnumerator(sourceAsList, partitionCount, i); } TraceHelpers.TraceInfo("ContigousRangePartitionExchangeStream::MakePartitions - (list) #{0} {1})", i, maxChunkSize); } } Contract.Assert(partitions.Length == partitionCount); m_partitions = partitions; } else { // We couldn't use an in-place partition. Shucks. Defer to the other overload which // accepts an enumerator as input instead. m_partitions = MakePartitions(source.GetEnumerator(), partitionCount); } }