using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Diagnostics;
const Int32 bits = 100_000_000;
Int32[] x = new Int32[n];
Int32[] y = new Int32[n];
Random random = new Random();
Int32[] split = new int[Environment.ProcessorCount];
Task[] tasks = new Task[split.Length];
Int32 take = (int)Math.Round((double)x.Length / tasks.Length, MidpointRounding.AwayFromZero);
for (int i = 0; i < n; i++)
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < n; i++) {
countOnes += Int32.PopCount( x[i] & y[i]);
stopwatch.Stop(); long elapsed = stopwatch.ElapsedMilliseconds;
foreach( var (a,b) in x.Zip(y) ) {
countOnesZip += Int32.PopCount( a & b);
stopwatch.Stop(); long elapsed_zip = stopwatch.ElapsedMilliseconds;
Partitioner<Tuple<int, int>> partitioner = Partitioner.Create(0, n);
Parallel.ForEach(partitioner, range =>
int startIndex = range.Item1;
int endIndex = range.Item2;
for (int i = startIndex; i < endIndex; i++)
localCountOnes += Int32.PopCount(x[i] & y[i]);
Interlocked.Add(ref countOnesPar, localCountOnes);
stopwatch.Stop(); long elapsed_par = stopwatch.ElapsedMilliseconds;
for (var i = 0; i < tasks.Length; i++)
tasks[i] = Task.Run(() =>
for (var index = taskNumber * take; index < (taskNumber + 1) * take && index < x.Length; index++)
localCount += int.PopCount(x[index] & y[index]);
split[taskNumber] = localCount;
await Task.WhenAll(tasks);
countOnesTask = split.Sum();
stopwatch.Stop(); long elapsed_task = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Processed {bits:N0} bits");
Console.WriteLine($"Elapsed time (For): {elapsed,18}ms Count: {countOnes:N0}");
Console.WriteLine($"Elapsed time (Parallel Tasks): {elapsed_task,7}ms Count: {countOnesTask:N0}");
Console.WriteLine($"Elapsed time (Parallel.ForEach): {elapsed_par,5}ms Count: {countOnesPar:N0}");
Console.WriteLine($"Elapsed time (Linq ForEach): {elapsed_zip,9}ms Count: {countOnesZip:N0}");