c++ - mas - grandes matrices, std:: vector y desbordamiento de pila
las empresas mas grandes de colombia 2018 (3)
Señalando tal vez un par de cosas pasadas por alto en las respuestas anteriores:
"El programa actuó de manera divertida omitiendo algunos pasos mientras se depuraba". OP, ¿puedes dar más detalles sobre lo que quieres decir? Tal vez, estaba depurando una compilación de lanzamiento, y mientras recorre el código observa que la línea de código que se está ejecutando no es la que espera ejecutar a continuación (que es el comportamiento perfectamente correcto para una compilación de lanzamiento con optimizaciones de compilador).
La pregunta decía que el compilador se bloqueó con un desbordamiento de pila. No es el programa ejecutado. Entonces el problema es un problema de compilación. Claro, cambiar el código puede hacer que el compilador no se bloquee, pero el comentario anterior sobre la asignación de std :: vector en la pila no está relacionado con lo que podría causar el bloqueo del compilador .
Sugerencias: podría intentar ver si hay algún error conocido en la versión del compilador que está utilizando (es decir, ver si su proveedor del compilador ha lanzado una versión más reciente que podría tratar el bloqueo del compilador).
Además, recogiendo específicamente su comentario de "nunca cambian de valor o tamaño", intente poner sus datos en matrices estáticas dobles const, en lugar de std :: vectores (o incluso listas vinculadas). Una lista de enlaces readonly asignada estáticamente inalterable es una especie de pérdida de tiempo cuando probablemente debería usar double []. los datos de const estáticos se inicializan en tiempo de compilación / enlace en lugar de en tiempo de ejecución, y existen en su propia área de memoria (estrictamente hablando).
Tengo un programa que está leyendo datos de grandes matrices, inicialmente dividí el programa en dos proyectos separados en Visual Studio y cada uno funcionaba bien por separado, pero cuando traté de ponerlos juntos, el programa actuó de manera extraña omitiendo algunos pasos mientras se depuraba. Soy muy nuevo en C ++, así que comencé a investigar y descubrí que tal vez estaba llenando la pila con esos enormes arreglos y que debería tratar de ponerlos en el montón.
Decidí cambiar cada una de las matrices por un std::vector
e inicializarlas de esta manera:
std::vector<double> meanTimeAO = { 0.4437, 0.441, 0.44206, 0.44632, 0.4508, 0.45425,...}
Pero después de cambiar todas las matrices ahora cuando intento compilar el compilador se bloquea con un desbordamiento de pila, pensé que estaba liberando espacio de memoria de la pila cambiando las matrices como un vector, pero parece que tuve los resultados opuestos, ¿por qué? ??
y ¿cómo debería lidiar con estos grandes arreglos? (se fijan sin cambiar los valores o el tamaño)
Como la respuesta de @ Ajay y el comentario de @Cornstalks señalan correctamente, puedes evitar la pila y el montón por completo usando un calificador static
o constexpr
en tu matriz
const static std::array<float, 1000000> a1 = {}; // OK
constexpr std::array<float, 1000000> a2 = {}; // OK in C++11 onwards
Esto almacena la matriz en la sección inicializada de datos de su memoria ( buena explicación aquí ). El const
solo sirve para no permitir la modificación de a1
, y no es necesario para evitar el desbordamiento de la pila. Las variables declaradas como constexpr
también son automáticamente const
y por lo tanto no necesitan el calificador.
Nota: También puede lograr los efectos de la static
haciendo que las variables globales de su matriz (s), aunque yo no lo recomendaría.
Desbordamiento de pila de programa
Si sus datos no son estáticos, debe usar std::vector
(u otros tipos de memoria asignada en el montón) cuando la cantidad de elementos sea muy grande.
std::array<float, 1000000> a = {}; // Causes stack-overflow on 32-bit MSVS 2015
std::vector<float> v(1000000); // OK
Esto se debe a que el tamaño de pila predeterminado es ~ 1 MB, y 1 millón de flotantes requiere ~ 4 MB. El tamaño del montón está limitado por la memoria disponible (RAM) del sistema. Más sobre la pila y el montón aquí .
Las desventajas de std::vector
son que es un poco más lento que std::array
(asignación de memoria de pila, desasignación y acceso es todo más lento que el de la pila), y que no es un tamaño fijo. Sin embargo, puede declarar su std::vector
como const
para evitar que usted (u otra persona) altere accidentalmente su tamaño o elementos.
const std::vector<float> v = {...};
Ahora en cuanto a por qué sus std::vector
s están causando desbordamientos de pila es un misterio. Sin embargo, mientras std::vector
asigna sus elementos en el montón, también asigna un puntero (4 bytes en 32 bits y 8 bytes en 64 bits) en la pila. Por lo tanto, si tiene más de ~ 250,000 std::vector
s en el alcance a la vez, esto también causará un desbordamiento de la pila (o ~ 125,000 en sistemas de 64 bits).
Desbordamiento de pila del compilador
El compilador, como cualquier programa, asigna memoria, algunos de los cuales estarán en la pila. El error oficial para un desbordamiento de pila del compilador en MSVC es Fatal Error C1063 .
Dado que su depurador se comporta de forma extraña, mi consejo sería tratar de aislar el código problemático dividiendo manualmente su código en unidades modulares y compilándolos individualmente. Es posible que una pequeña cantidad de código pueda ser responsable del error, al consumir mucha pila, por ejemplo, al generar recursivamente una gran cantidad de funciones.
Alternativamente, puede ser que su código sea tan intrínsecamente complicado que, naturalmente, requiera más memoria de la que tiene la pila. En ese caso, dividir su código aún será beneficioso, pero también podría intentar aumentar el tamaño de pila predeterminado de MSVC .
Mejorando tu código
Para mejorar tu código, puedes intentar dividir tus datos en fragmentos. Por ejemplo, podría: leer en ~ 256 KB valor de la matriz, procesarlo, escribir la matriz de nuevo en el archivo, luego pasar a los siguientes 256 KB. También puede elegir que el tamaño del fragmento sea menor que el tamaño de su caché L1 (para que todo pueda almacenarse a la vez), lo que mejoraría el rendimiento al minimizar las fallas del caché.
Notas
MSVS 2015 (actualización 2) produce un error de compilación interno al compilar
#include "stdafx.h" #include <array> int main() { constexpr std::array<int, 1000000> a = {}; return 0; }
La variante de
static const
funciona bien, y si muevoa
main externo (convirtiéndola en una variable global) entonces también funciona bien.No tener un chkstk.asm es inusual. El mío está ubicado en
C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/crt/src/i386/chkstk.asm
. Si te lo estás perdiendo, intenta reinstalar MS Visual Studio.
Si la matriz es de tamaño fijo y sus elementos no cambian, no hay necesidad real de usar vector
. Puede usar std::array
, array of const
o constexpr
en constexpr
lugar.
constexpr float meanTimeAO[] = { 0.4437f, 0.441f, 0.44206f, 0.44632f, 0.4508f, 0.45425f,...}