Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

218
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!