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

118
Views
Tratar con listas muy grandes en x86

Necesito trabajar con grandes listas de flotantes, pero estoy llegando a los límites de memoria en los sistemas x86. No sé la longitud final, por lo que necesito usar un tipo expandible. En sistemas x64, puedo usar <gcAllowVeryLargeObjects> .

Mi tipo de datos actual:

 List<RawData> param1 = new List<RawData>(); List<RawData> param2 = new List<RawData>(); List<RawData> param3 = new List<RawData>(); public class RawData { public string name; public List<float> data; }

La longitud de las listas de parámetros es baja (actualmente 50 o menos), pero los datos pueden ser de más de 10 m. Cuando la longitud es 50, alcanzo los límites de memoria ( OutOfMemoryException ) justo por encima de 1 m de puntos de datos, y cuando la longitud es de 25, alcanzo el límite justo por encima de 2 m de puntos de datos. (Si mis cálculos son correctos, eso es exactamente 200 MB, más el tamaño del nombre, más los gastos generales). ¿Qué puedo usar para aumentar este límite?

Editar: Intenté usar List<List<float>> con un tamaño máximo de lista interna de 1 << 17 (131072), lo que aumentó un poco el límite, pero aún no tanto como quiero.

Edit2: Intenté reducir el tamaño del fragmento en la Lista> a 8192, y obtuve OOM en ~ 2,3 millones de elementos, con el administrador de tareas leyendo ~ 1,4 GB para el proceso. Parece que necesito reducir el uso de memoria entre la fuente de datos y el almacenamiento, o activar GC con más frecuencia: pude recopilar 10 millones de puntos de datos en un proceso x64 en una PC con 4 GB de RAM, IIRC el proceso nunca superó los 3 GB

Edit3: condensé mi código a solo las partes que manejan los datos. http://pastebin.com/maYckk84

Edit4: eché un vistazo a DotMemory y descubrí que mi estructura de datos ocupa ~ 1 GB con la configuración que estaba probando (50 canales * 3 parámetros * 2 millones de eventos = 300 000 000 elementos flotantes). Supongo que tendré que limitarlo en x86 o descubrir cómo escribir en el disco en este formato a medida que obtengo datos.

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

En primer lugar, en los sistemas x86, el límite de memoria es de 2 GB, no de 200 MB. Supongo que su problema es mucho más complicado que eso. Tiene una fragmentación agresiva de LOH (montón de objetos grandes).
CLR usa montones diferentes para objetos pequeños y grandes. El objeto es grande si su tamaño supera los 85.000 bytes. LOH es una cosa muy conflictiva, no está ansioso por devolver la memoria no utilizada al sistema operativo, y es muy pobre en la desfragmentación.
.Net List es una implementación de la estructura de datos ArrayList, almacena elementos en una matriz, que tiene un tamaño fijo; cuando se llena la matriz, se crea una nueva matriz con el doble de tamaño. Ese crecimiento continuo de la matriz con su cantidad de datos es un escenario de "hambruna" para LOH.
Por lo tanto, debe utilizar una estructura de datos personalizada para satisfacer sus necesidades. Por ejemplo, una lista de fragmentos, con cada fragmento lo suficientemente pequeño como para no entrar en LOH. Aquí hay un pequeño prototipo:

 public class ChunkedList { private readonly List<float[]> _chunks = new List<float[]>(); private const int ChunkSize = 8000; private int _count = 0; public void Add(float item) { int chunk = _count / ChunkSize; int ind = _count % ChunkSize; if (ind == 0) { _chunks.Add(new float[ChunkSize]); } _chunks[chunk][ind] = item; _count ++; } public float this[int index] { get { if(index <0 || index >= _count) throw new IndexOutOfRangeException(); int chunk = index / ChunkSize; int ind = index % ChunkSize; return _chunks[chunk][ind]; } set { if(index <0 || index >= _count) throw new IndexOutOfRangeException(); int chunk = index / ChunkSize; int ind = index % ChunkSize; _chunks[chunk][ind] = value; } } //other code you require }

Con ChunkSize = 8000, cada fragmento ocupará solo 32 000 bytes, por lo que no entrará en LOH. _chunks ingresará a LOH solo cuando haya alrededor de 16,000 fragmentos en la colección, que es más de 128 millones de elementos en la colección (alrededor de 500 MB).

UPD He realizado algunas pruebas de estrés para la muestra anterior. El sistema operativo es x64, la plataforma de solución es x86. Tamaño de fragmento es 20000.

Primero:

 var list = new ChunkedList(); for (int i = 0; ; i++) { list.Add(0.1f); }

OutOfMemoryException se genera en ~324,000,000 elementos

Segundo:

 public class RawData { public string Name; public ChunkedList Data = new ChunkedList(); } var list = new List<RawData>(); for (int i = 0;; i++) { var raw = new RawData { Name = "Test" + i }; for (int j = 0; j < 20 * 1000 * 1000; j++) { raw.Data.Add(0.1f); } list.Add(raw); }

La excepción OutOfMemoryException se genera en i=17, j~12 000 000. 17 instancias RawData creadas con éxito, 20 millones de puntos de datos por cada una, alrededor de 352 millones de puntos de datos en total.

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!