public static void For(int from, int to, DelegateFor delFor) { DelegateProcess process = delegate(int chunkStart, int chunkEnd) { for (int i = chunkStart; i < chunkEnd; ++i) { delFor(i); } }; int cores = Environment.ProcessorCount; int chunks = (to - from) / cores; IAsyncResult[] asyncResults = new IAsyncResult[cores]; int end = 0; for (int i = 0; i < cores; ++i) { int start = i * chunks; end = Math.Min(start + chunks, to); asyncResults [i] = process.BeginInvoke(start, end, null, null); } for (int i = end; i < to; ++i) { delFor(i); } for (int i = 0; i < cores; ++i) { process.EndInvoke(asyncResults [i]); } }
/// <summary> /// Parallel for loop. Invokes given action, passing arguments /// fromInclusive - toExclusive on multiple threads. /// Returns when loop finished. /// </summary> public static void For(int fromInclusive, int toExclusive, ForDelegate forDelegate) { // chunkSize = 1 makes items to be processed in order. // Bigger chunk size should reduce lock waiting time and thus // increase paralelism. int chunkSize = 4; // number of process() threads int threadCount = Environment.ProcessorCount; int index = fromInclusive - chunkSize; // locker object shared by all the process() delegates object locker = new object(); // processing function // takes next chunk and processes it using action DelegateProcess process = delegate() { while (true) { int chunkStart = 0; lock (locker) { // take next chunk index += chunkSize; chunkStart = index; } // process the chunk // (another thread is processing another chunk // so the real order of items will be out-of-order) for (int i = chunkStart; i < chunkStart + chunkSize; i++) { if (i >= toExclusive) { return; } forDelegate(i); } } }; // launch process() threads IAsyncResult[] asyncResults = new IAsyncResult[threadCount]; for (int i = 0; i < threadCount; ++i) { asyncResults[i] = process.BeginInvoke(null, null); } // wait for all threads to complete for (int i = 0; i < threadCount; ++i) { process.EndInvoke(asyncResults[i]); } }
/// <summary> /// Parallel for loop. Invokes given action, passing arguments /// fromInclusive - toExclusive on multiple threads. /// Returns when loop finished. /// </summary> /// <param name="chunkSize"> /// chunkSize = 1 makes items to be processed in order. /// Bigger chunk size should reduce lock waiting time and thus /// increase paralelism. /// </param> /// <param name="threadCount">number of process() threads</param> public static void For(int fromInclusive, int toExclusive, int chunkSize, int threadCount, ForDelegate forDelegate) { int index = fromInclusive - chunkSize; // locker object shared by all the process() delegates object locker = new object(); // processing function // takes next chunk and processes it using action DelegateProcess process = delegate() { while (true) { int chunkStart = 0; lock (locker) { // take next chunk index += chunkSize; chunkStart = index; } // process the chunk // (another thread is processing another chunk // so the real order of items will be out-of-order) for (int i = chunkStart; i < chunkStart + chunkSize; i++) { if (i >= toExclusive) { return; } forDelegate(i); } } }; // launch process() threads IAsyncResult[] asyncResults = new IAsyncResult[threadCount]; for (int i = 0; i < threadCount; ++i) { asyncResults[i] = process.BeginInvoke(null, null); } // wait for all threads to complete for (int i = 0; i < threadCount; ++i) { process.EndInvoke(asyncResults[i]); } }