Una gran pregunta. En su ejemplo, el nivel de paralelización es bastante bajo incluso en un procesador de cuatro núcleos, pero con un poco de espera, el nivel de paralelización puede ser bastante alto.
// Max concurrency: 5
[Test]
public void Memory_Operations()
{
ConcurrentBag<int> monitor = new ConcurrentBag<int>();
ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
var arrayStrings = new string[1000];
Parallel.ForEach<string>(arrayStrings, someString =>
{
monitor.Add(monitor.Count);
monitor.TryTake(out int result);
monitorOut.Add(result);
});
Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}
Ahora mire lo que sucede cuando se agrega una operación de espera para simular una solicitud HTTP.
// Max concurrency: 34
[Test]
public void Waiting_Operations()
{
ConcurrentBag<int> monitor = new ConcurrentBag<int>();
ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
var arrayStrings = new string[1000];
Parallel.ForEach<string>(arrayStrings, someString =>
{
monitor.Add(monitor.Count);
System.Threading.Thread.Sleep(1000);
monitor.TryTake(out int result);
monitorOut.Add(result);
});
Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}
Todavía no he realizado ningún cambio y el nivel de simultaneidad/paralelización ha aumentado drásticamente. La concurrencia puede tener su límite aumentado con ParallelOptions.MaxDegreeOfParallelism
.
// Max concurrency: 43
[Test]
public void Test()
{
ConcurrentBag<int> monitor = new ConcurrentBag<int>();
ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
var arrayStrings = new string[1000];
var options = new ParallelOptions {MaxDegreeOfParallelism = int.MaxValue};
Parallel.ForEach<string>(arrayStrings, options, someString =>
{
monitor.Add(monitor.Count);
System.Threading.Thread.Sleep(1000);
monitor.TryTake(out int result);
monitorOut.Add(result);
});
Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}
// Max concurrency: 391
[Test]
public void Test()
{
ConcurrentBag<int> monitor = new ConcurrentBag<int>();
ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
var arrayStrings = new string[1000];
var options = new ParallelOptions {MaxDegreeOfParallelism = int.MaxValue};
Parallel.ForEach<string>(arrayStrings, options, someString =>
{
monitor.Add(monitor.Count);
System.Threading.Thread.Sleep(100000);
monitor.TryTake(out int result);
monitorOut.Add(result);
});
Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}
Recomendar configuración ParallelOptions.MaxDegreeOfParallelism
. No necesariamente aumentará el número de subprocesos en uso, pero garantizará que solo comience una cantidad de subprocesos, lo cual parece ser su preocupación.
Por último, para responder a su pregunta, no obtendrá todos los hilos para comenzar de una vez. Use Parallel.Invoke si desea invocar en paralelo a la perfección, p. probando las condiciones de carrera.
// 636462943623363344
// 636462943623363344
// 636462943623363344
// 636462943623363344
// 636462943623363344
// 636462943623368346
// 636462943623368346
// 636462943623373351
// 636462943623393364
// 636462943623393364
[Test]
public void Test()
{
ConcurrentBag<string> monitor = new ConcurrentBag<string>();
ConcurrentBag<string> monitorOut = new ConcurrentBag<string>();
var arrayStrings = new string[1000];
var options = new ParallelOptions {MaxDegreeOfParallelism = int.MaxValue};
Parallel.ForEach<string>(arrayStrings, options, someString =>
{
monitor.Add(DateTime.UtcNow.Ticks.ToString());
monitor.TryTake(out string result);
monitorOut.Add(result);
});
var startTimes = monitorOut.OrderBy(x => x.ToString()).ToList();
Console.WriteLine(string.Join(Environment.NewLine, startTimes.Take(10)));
}
que estaba usando Parallel.ForEach (FilePathArray, path => ... leer unos 24.000 archivos de esta noche la creación de un nuevo archivo para cada archivo que he leído en. Código muy simple. Parece que incluso los 6 hilos fue suficiente para abrumar el disco de 7200 RPM que estaba leyendo al 100% de utilización. Durante el período de unas pocas horas vi la biblioteca de Parallel hacer girar más de 8,000 hilos. Probé usando MaxDegreeOfParallelism y efectivamente desaparecieron los 8000+ hilos. Lo he probado varias veces ahora con el mismo resultado. –
Es * podría * iniciar 1000 hilos para algunos 'DoSomething' degenerados. (Como en el caso en el que actualmente estoy lidiando con un problema en el código de producción que no pudo establecer un límite y engendró más de 200 subprocesos por lo que aparece el grupo de conexiones de SQL .. Recomiendo configurar el DOP máximo para cualquier trabajo que no se puede razonar trivialmente como explícitamente vinculado a la CPU.) – user2864740