2010-09-22 11 views
11

Estoy implementando un programa secuencial para ordenar como quicksort. Me gustaría probar el rendimiento de mi programa en una gran variedad de 1 o 10 mil millones de enteros. Pero el problema es que obtengo un error de segmentación debido al tamaño de la matriz.¿Cómo declarar y usar grandes matrices de mil millones de enteros en C?

Un código de ejemplo de declaración de esta matriz:

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#define N 1000000000 

int main(int argc, char **argv) 
{ 
    int list[N], i; 
    srand(time(NULL)); 
    for(i=0; i<N; i++) 
    list[i] = rand()%1000; 
    return 0; 
} 

tengo una propuesta para utilizar la función mmap. Pero no sé cómo usarlo? ¿Alguien puede ayudarme a usarlo?

Estoy trabajando en Ubuntu 10.04 64-bit, gcc versión 4.4.3.

Gracias por sus respuestas.

+2

¿Cuánta memoria física tiene su computadora? – BlueCode

+5

@BlueCode: Probablemente eso no importe; es la memoria virtual lo que importa; no toda la memoria asignada en el espacio de direcciones de un proceso debe ser respaldada inmediatamente por la RAM. –

+0

intente ponerlo en el montón en lugar de la pila. Es bastante probable que el tamaño máximo de la pila esté limitado por el sistema operativo o el tiempo de ejecución c – pm100

Respuesta

6

Michael tiene razón, no puede caber tanto en la pila. Sin embargo, puede hacerlo global (o estático) si no desea malloc.

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#define N 1000000000 
int list[N]; 

int main(int argc, char **argv) 
{ 
    int i; 
    srand(time(NULL)); 
    for(i=0; i<N; i++) 
    list[i] = rand()%1000; 
    return 0; 
} 
+0

Gracias por las respuestas. He probado el uso de la asignación dinámica con malloc y el uso de una variable global. Estas dos soluciones funcionan de manera efectiva, pero el uso de un parámetro global induce una compilación que lleva mucho tiempo (aproximadamente 8 minutos). – semteu

+0

¿Cómo funciona la declaración global? –

+1

@dlpcoder: intente leer algo como esto: http://www.geeksforgeeks.org/memory-layout-of-c-program/ – nmichaels

10

Debe utilizar malloc para este tipo de asignación. Eso en la pila fallará casi todo el tiempo.


int *list; 

list = (int *) malloc(N * sizeof(int)); 

Esto coloca la asignación en el montón donde hay mucha más memoria disponible.

+0

. Debe tener cuidado, 'malloc (N * sizeof (int))' también puede fallar, algunos compiladores agregan una limitación al máximo plato contiguo que puede ser asignado. – jbernadas

+4

y N * sizeof (int) es probable que se desborde en una computadora de 32 bits por cierto. –

3

Probablemente no crees una matriz tan grande y si lo haces, ciertamente no la creas en la pila; la pila simplemente no es tan grande.

Si tiene un espacio de direcciones de 32 bits y un int de 4 bytes, entonces no puede crear una matriz con mil millones int s; simplemente no habrá suficiente espacio contiguo en la memoria para ese objeto grande (probablemente no habrá suficiente espacio contiguo para un objeto una fracción de ese tamaño). Si tiene un espacio de direcciones de 64 bits, puede salirse con la suya asignando ese espacio.

Si realmente quieres probar, deberás crearlo estáticamente (es decir, declarar la matriz en el alcance del archivo o con el calificador static en la función) o dinámicamente (usando malloc).

+0

El póster OP indica que se trata de una máquina de 64 bits, por lo que debe caber en el espacio de direcciones virtuales. –

0

Otra opción es asignar dinámicamente una lista vinculada de matrices más pequeñas. Tendrás que envolverlos con funciones de acceso, pero es mucho más probable que puedas tomar 16 256 MB de memoria que un solo fragmento de 4 GB.

typedef struct node_s node, *node_ptr; 
struct node_s 
{ 
    int data[N/NUM_NODES]; 
    node_ptr next; 
}; 
+0

Gracias por su propuesta, creo que será difícil aplicar un algoritmo de clasificación simple como quicksort en este tipo de estructura de datos. – semteu

2

en sistemas Linux malloc de grandes trozos apenas hace un mmap bajo el capó, por lo que es tal vez demasiado tedioso para mirar en eso.

Tenga cuidado de no tener desbordamiento (enteros con signo) ni envolvente silenciosa (enteros sin signo) para sus límites e índices de matriz. Utilice size_t como un tipo para eso, ya que está en una máquina de 64 bits, esto debería funcionar.

Pero como hábito definitivamente debe verificar sus límites contra SIZE_MAX, algo así como assert(N*sizeof(data[0]) <= SIZE_MAX), para estar seguro.

2

Las asignaciones de pila lo hacen romperse. N = 1Gig ints => 4Gig de memoria (ambos con un compilador de 32 bits y uno de 64 bits).Pero si quiere medir el rendimiento del servicio rápido, o un algoritmo similar al suyo, esta no es la manera de hacerlo. Intente en su lugar usar múltiples quicksorts en secuencia en muestras preparadas con un tamaño grande.

-create a large random sample not more than half your available memory. 
make sure it doesn''t fill your ram! 
If it does all measuring efforts are in vain. 
500 M elements is more than enough on a 4 gig system. 

-decide on a test size (e.g. N = 100 000 elements) 
-start timer 
--- do the algoritm for (*start @ i*N, *end @ (i+1)*N) 
(rinse repeat for next i until the large random sample is depleted) 
-end timer 

Ahora tiene una respuesta muy precisa a la cantidad de tiempo que su algoritmo ha consumido. Ejecútelo varias veces para tener una idea de "qué tan preciso" (use una nueva semilla srand (semilla) cada vez). Y cambie la N para más inspección.

Cuestiones relacionadas