Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

217
Visualizações
Las operaciones anidadas paralelas devuelven resultados extraños

Estoy tratando de usar la biblioteca Parallel para mi código y me enfrento a un problema extraño. Hice un programa corto para demostrar el comportamiento. En resumen, hago 2 bucles (uno dentro de otro). El primer ciclo genera una matriz aleatoria de 200 enteros y el segundo ciclo agrega todas las matrices en una lista grande. El problema es que, al final, no obtengo un múltiplo de 200 enteros, sino que veo que algunas ejecuciones no esperan a que la matriz aleatoria se cargue por completo. Es difícil de explicar, así que aquí el código de muestra:

 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace TestParallel { class Program { static int RecommendedDegreesOfParallelism = 8; static int DefaultMaxPageSize = 200; static void Main(string[] args) { int maxPage = 50; List<int> lstData = new List<int>(); Parallel.For(0, RecommendedDegreesOfParallelism, new ParallelOptions() { MaxDegreeOfParallelism = RecommendedDegreesOfParallelism }, (index) => { int cptItems = 0; int cptPage = 1 - RecommendedDegreesOfParallelism + index; int idx = index; do { cptPage += RecommendedDegreesOfParallelism; if (cptPage > maxPage) break; int Min = 0; int Max = 20; Random randNum = new Random(); int[] test2 = Enumerable .Repeat(0, DefaultMaxPageSize) .Select(i => randNum.Next(Min, Max)) .ToArray(); var lstItems = new List<int>(); lstItems.AddRange(test2); var lstRes = new List<int>(); lstItems.AsParallel().WithDegreeOfParallelism(8).ForAll((item) => { lstRes.Add(item); }); Console.WriteLine($"{Task.CurrentId} = {lstRes.Count}"); lstData.AddRange(lstRes); cptItems = lstRes.Count; } while (cptItems == DefaultMaxPageSize); } ); Console.WriteLine($"END: {lstData.Count}"); Console.ReadKey(); } } }

Y aquí hay un registro de ejecución:

 4 = 200 1 = 200 2 = 200 3 = 200 6 = 200 5 = 200 7 = 200 8 = 200 1 = 200 6 = 194 2 = 191 5 = 200 7 = 200 8 = 200 4 = 200 5 = 200 3 = 182 4 = 176 8 = 150 7 = 200 5 = 147 1 = 200 7 = 189 1 = 200 1 = 198 END: 4827

Podemos ver que algunos bucles devuelven menos de 200 elementos. ¿Como es posible?

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Esto aquí no es seguro para subprocesos:

 lstItems.AsParallel().WithDegreeOfParallelism(8).ForAll((item) => { lstRes.Add(item); });

De la documentación para List<T> :

Es seguro realizar varias operaciones de lectura en una lista, pero pueden surgir problemas si se modifica la colección mientras se lee. Para garantizar la seguridad de los subprocesos, bloquee la colección durante una operación de lectura o escritura. Para habilitar el acceso a una colección por múltiples subprocesos para lectura y escritura, debe implementar su propia sincronización.

No lo menciona explícitamente, pero .Add() también puede fallar cuando varios subprocesos lo llaman simultáneamente.

La solución sería bloquear las llamadas a List<T>.Add() en el ciclo anterior, pero si lo hace, es probable que sea más lento que simplemente agregar los elementos en un ciclo en un solo hilo.

 var locker = new object(); lstItems.AsParallel().WithDegreeOfParallelism(8).ForAll((item) => { lock (locker) { lstRes.Add(item); } });
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda