¿Por qué se necesita una administración de memoria personalizada para los activos?

10

Casi todos los recursos relacionados con la programación de juegos, especialmente los juegos de mundo abierto en 3D, hablan de cómo debe estar constantemente descargando y recargando activos hacia y desde el disco, la memoria del sistema y la memoria de video. Puedo entender esto en las consolas, ya que tienen esquemas de administración de memoria muy simples que no pueden manejar ningún desbordamiento potencial.

Sin embargo, en la PC, la situación es muy diferente. El sistema operativo proporciona memoria virtual para la memoria del sistema y el controlador de gráficos maneja el intercambio de la CPU a la GPU. Entonces, ¿por qué no es suficiente cargar todo de una vez y solo tener que lidiar con la captación previa y posiblemente asegurarse de que no haya bloqueo mientras se intercambia un activo requerido?


Esto no quiere decir que todo se está asignando ingenuamente usando algo como malloc. Todo se mantendrá contiguo y coherente en caché. Podría decirse que es más fácil hacer que su acceso a la memoria sea eficiente si no tiene que preocuparse por la paginación de entrada y salida manual de todos modos ...


ACTUALIZAR:

Después de leer un poco sobre las transferencias asíncronas de búfer , tengo la idea de que la forma en que el controlador de gráficos puede localizar y recuperar automáticamente la memoria es subóptima. ¿Esto también es válido para los recursos de la CPU; es decir, ¿es mejor administrar siempre manualmente cuando un recurso dado debe cargarse y descargarse incluso en presencia de memoria virtual?

jmegaffin
fuente
1
Está suponiendo que el contenido del activo se almacena en la memoria del sistema. Gran parte de los datos de sus activos se almacenarán en la memoria de la GPU, que es mucho más limitada.
dadoo Games
Al leer la respuesta aquí, tengo la idea de que los controladores OpenGL también mantienen automáticamente todos los búferes / texturas en la CPU. Sin embargo, puedo ver por qué podría ser útil especificar estas transferencias manualmente para aprovechar las cargas asincrónicas .
jmegaffin
¿Estás seguro de que esto es relevante para tu proyecto de juego? No estoy seguro de ver el desafío técnico, solo la solución. Si no enfrenta un desafío técnico, es difícil adaptar una solución o comprenderla.
AturSams
Me pregunto por qué los motores de juego implementan sistemas complejos de almacenamiento en caché de activos cuando los sistemas / controladores operativos ya tienen sistemas de memoria virtual disponibles. Es relevante para mí porque estoy escribiendo un juego de mundo abierto donde esta información es muy importante.
jmegaffin
¿Su juego sufre problemas de rendimiento y la herramienta de creación de perfiles muestra que se debe al acceso a la memoria? El problema con los juegos que contienen niveles abiertos es que, en términos técnicos, esto se traduce en una gran cantidad de datos. Cuanto más control tenga sobre esos datos, mejor será el rendimiento. ¿Por qué no implementar el sistema más eficiente para administrar datos? El desarrollo del juego es muy competitivo y cuando tienes dinero para expertos, no vas a dejar ninguna piedra sin mover, buscando exprimir más detalles y mayores fps.
AturSams

Respuestas:

16

Los juegos modernos de mundo abierto simplemente no caben en la memoria. Tenga en cuenta que la mayoría de los juegos siguen siendo de 32 bits debido a la cantidad de jugadores con sistemas operativos de 32 bits, y un proceso de 32 bits en el mejor de los casos solo puede tener 4 GB de memoria direccionada a la vez (independientemente de la memoria virtual), pero es realista limitado a 2-3 GB. Agregue fragmentación y la cantidad real de objetos utilizables que puede tener en una memoria a la vez es un poco más pequeña que la información total que necesita para un entorno grande. Incluso en un sistema operativo de 64 bits, a menudo necesita apuntar a máquinas de baja especificación con solo 4 GB de memoria para garantizar la máxima compatibilidad del usuario final. No olvidemos los dispositivos móviles, hardware "con poca potencia" como WiiU, etc. Los desarrolladores tienen que apuntar a mucho más que grandes equipos de PC de juegos de fantasía.

La memoria virtual no es una solución, en primer lugar porque no niega las limitaciones de espacio de direcciones y también porque no es óptima. El sistema operativo puede localizar cosas en momentos inoportunos o de maneras inoportunas. Este fue un problema tratado por los sistemas operativos cuando se produjo la hibernación por primera vez; la paginación de los procesos al disco y luego volver a paginarlos fue significativamente más lenta en algunos casos que hacer que la aplicación vuelva a transmitir el recurso explícitamente. Todavía puede ver los problemas hoy cuando un sistema se está quedando sin memoria, las páginas se paginan a disco, y el sistema deja de responder se convierte en elementos críticos necesarios para ejecutar su WM / explorer.exe para obtener paginación. La memoria virtual fue una solución ideada para un problema hace décadas donde los sistemas tenían muy poca RAM y la brecha entre la memoria y las velocidades del disco era mucho menor. Incluso hoy' Los SSD más rápidos son una pequeña fracción de la velocidad de la RAM barata / lenta, y tratar de pretender que puedes usar tu disco como RAM virtual ya no es la mejor idea. Esta es una época en la que algunas personas hacen lo contrario y cargan los sistemas de archivos en discos RAM; Las restricciones que llevaron a la creación de la memoria virtual ya no son ciertas.

Incluso aparte del problema del disco, la gestión personalizada de recursos sigue siendo una gran parte del desarrollo del juego. Desde la eliminación de errores hasta problemas de fragmentación hasta la transmisión inteligente de recursos complejos, simplemente pretender que todo el mundo es una caja de bits infinitamente grande no es realista.

Sean Middleditch
fuente
Gracias por la respuesta detallada. Aunque todavía estoy buscando información sobre la forma en que los controladores de GPU manejan la memoria virtual (entre VRAM y la RAM del sistema).
jmegaffin
@Boreal: mismos problemas. Simplemente reemplace "RAM" con "VRAM" y "disco" con "memoria de CPU"
Sean Middleditch
@SeanMiddleditch +1 Buena respuesta, "Esta es una época en la que algunas personas hacen lo contrario y cargan los sistemas de archivos en discos RAM" ¿te refieres a los archivos mapeados de memoria? Además, lo que entiendo por su respuesta es que el asignador de memoria personalizado evita que el sistema operativo elimine la memoria, ¿no es este el caso? la paginación en la PC se evita exactamente usando un asignador de memoria personalizado?
concept3d
1
@ concept3d: no mapeo de memoria, sino discos RAM literales. Puede hacer una unidad que esté respaldada por la memoria y no por el disco. El administrador de memoria personalizado no impide la paginación (alguna otra aplicación podría estar utilizando toda la memoria). Administrar recursos de forma inteligente (en la capa de administración de objetos / recursos) simplemente significa que libera memoria para objetos que ya no necesita. Piense en los cachés de disco del sistema operativo que guarda en la memoria
Sean Middleditch
6

Para un juego de 32 bits, como la mayoría de los juegos son por una variedad de razones, incluso un juego que viene en un DVD de una sola cara (4.3GB) ya tiene mucho más contenido que se puede ajustar en un espacio de direcciones de 32 bits. Y suponiendo que el contenido no esté comprimido en el disco, y que sea perfectamente óptimo, cargue todo a la vez en un enfoque de espacio de direcciones contiguo. Muchos juegos ahora vienen en múltiples DVD, superando fácilmente los 10 GB de contenido. En mi experiencia en PC, una vez que su espacio de direcciones se acerca a las asignaciones de 2GB comenzará a fallar, y eso se convierte en un límite difícil, independientemente de la cantidad de memoria física que tenga el usuario.

Si realiza el salto a 64 bits, suponiendo que su motor lo admita, ese límite duro desaparece, solo para ser reemplazado por un límite suave efectivo: tan pronto como comience el intercambio de memoria virtual, el rendimiento del juego disminuirá inaceptablemente Si el proceso principal alguna vez tiene que esperar a que se vuelva a paginar la memoria, la velocidad de fotogramas tartamudeará y fallará. La memoria virtual puede hacerlo transparente, pero no lo hace eficiente. Físicamente toma tiempo recuperar esa memoria del disco, y mientras espera, su juego se ha estancado. Si bien es posible evitarlo (con la búsqueda previa en segundo plano de páginas de memoria que sabe que necesitará pronto), es un proceso difícil y poco confiable, y aún tendrá implicaciones de rendimiento.

Los algoritmos del sistema operativo para decidir qué páginas intercambiar en el disco no tienen conocimiento de su juego y de lo que probablemente necesitará a continuación. Además, el sistema operativo aún debe admitir otras aplicaciones que se ejecutan simultáneamente con su juego, así como el sistema operativo en sí. Tener que detenerse mientras se devuelven las páginas del disco es un golpe de rendimiento masivo, y no importa si es su juego, otra aplicación o el sistema operativo que lo incurre, el rendimiento del juego sufrirá enormemente.

Entonces, independientemente de si el límite de memoria es suave o duro, la memoria sigue siendo limitada. Pero incluso si pudiera cargar todo de una vez, sin alcanzar un límite de rendimiento, todavía hay razones por las que no querría:

  1. Su juego tarda mucho más en cargarse y llegar a un estado interactivo de lo que necesita, porque simplemente carga todo al principio y lo mantiene residente. Puede cargar aproximadamente 150 MB / seg. Desde un disco duro, e incluso la unidad de DVD más rápida (24x) se carga a 33 MB / seg. Eso significa que el contenido de DVD de 4.3GB de ejemplo tomará al menos 30 segundos en cargarse desde el HDD, y más de 133 segundos en cargarse desde DVD. Esos son tiempos de carga inaceptablemente largos.

  2. Tu juego requiere mucha más memoria de la justificada. Si solo el 10% del contenido es visible en cualquier momento, mantener al residente restante es simplemente un desperdicio y evita que el usuario use esa memoria para otra cosa. Los usuarios generalmente no perdonan los juegos que requieren una cantidad desproporcionadamente grande de memoria para funcionar correctamente.

La transmisión de activos desde el disco de forma dinámica, ya sea en segundo plano o sincrónicamente durante una pantalla de carga, le permite ser mucho más eficiente en el uso de la memoria, con un esfuerzo insignificante y solo un inconveniente menor para el usuario. Pero es una optimización y, como cualquier otra optimización, tiene rendimientos decrecientes cuanto más intente aplicarla. En algún momento, el aumento de la huella de memoria para mantener algo residente se ve compensado por las ventajas obtenidas de tenerlo allí sin la necesidad de cargarlo. Pero hasta llegar a ese punto, es mejor cargar solo lo que necesita, cuando lo necesita.

MrCranky
fuente
1

Simplemente hablando de manera muy general y simplista, y sin considerar los detalles de las implementaciones de memoria virtual, el desarrollador siempre tiene el conocimiento de la falta de implementación de VM.

El desarrollador siempre puede decir: "No necesito cargar este archivo de audio en este momento. La música en el interior solo se usa para el juego en pantalla". E inmediatamente después del juego en pantalla, el desarrollador puede decir: "Ya no necesito este clip de audio en la memoria física. Solo se usa para este juego en pantalla".

El sistema operativo no tiene tal previsión. Es posible que pueda descubrir, muchas fallas en la página más adelante, que algunos clips de audio ya no son necesarios en la memoria física, ya que no se ha accedido en un buen tiempo. Pero convertir la previsión en retrospectiva se traduce en muchas fallas de página, y muchas fallas de página se traducen en problemas en las velocidades de cuadros en un software tan crítico como un videojuego. Allí, la previsión del desarrollador realmente ayuda si desea evitar tales contratiempos.

Y eso se aplica conceptualmente independientemente del hardware y el software. Asumir que la paginación en la memoria es costosa, entonces la previsión del desarrollador siempre ayudará a reducir ese gasto.

Hablando aún más ampliamente, hay un ciclo interminable entre el diseñador de hardware, el diseñador de compiladores, el diseñador de SO / controladores y el desarrollador de aplicaciones. Los desarrolladores de hardware / compilador / SO / controlador a menudo intentan implementar optimizaciones para acelerar su aplicación promedio en función de sus patrones habituales de acceso a la memoria, y tal vez a veces con la esperanza de que "la gente debería poder escribir el código como quiera y debe ser rápido ".Pero si se pensaba que ese tipo estaba sucediendo, generalmente falla para los campos críticos para el rendimiento, porque luego los desarrolladores críticos para el rendimiento comienzan a aprender los intrincados detalles de su compilador, hardware, sistema operativo, controladores, etc. y comienzan a escribir código específicamente diseñado para explotar eso tanto como sea posible para escribir el código más rápido posible (como captaciones previas, división de campo en frío / caliente, SoAs, etc. para código compatible con caché). Y eso es como un juego que nunca termina. Estas cosas nunca se tratan como cajas negras en los campos críticos para el rendimiento, ya que los desarrolladores compiten por el rendimiento.

Personalmente, desearía que la memoria virtual no existiera, ya que agrega una capa adicional de imprevisibilidad de rendimiento de formas que tienden a ser demasiado extremas e incurren en una penalización de rendimiento demasiado cuando las cosas van realmente al sur hasta el punto de inutilización. A veces me he topado con casos en los que utilicé alguna aplicación en la que escribí uno o dos dígitos extra por accidente cuando estaba borracho en un campo de entrada que luego agotó la memoria física tan rápidamente que hizo que el sistema operativo se detuviera donde no podía Ni siquiera hice clic en el botón Cancelar en la barra de progreso y tuve que esperar 10 minutos mientras apretaba Ctrl + Alt + Supr para matar un proceso y me maldecía a mí mismo mientras derramaba mi bebida para volver a un punto donde las cosas se pueden volver a usar, y eso fue a pesar de que el archivo de la página se almacena en un SSD. En esos casos, preferiría un error de "falta de memoria" o algo así, en ese momento podría cerrar algunas de mis 17 pestañas de pornografía (está bien, marco mis favoritos de todos modos) para liberar algo de memoria y luego continuar de inmediato. reanudar mi negocio


fuente