Mejorar el rendimiento del motor de programación

Nota:

Los grupos de interés de la comunidad ahora se han movido de Yammer a Microsoft Viva Engage. Para unirse a una comunidad de Viva Engage y participar en las últimas discusiones, complete el formulario Solicitud de acceso a la Comunidad de Viva Engage de Finanzas y Operaciones y elija la comunidad a la que desea unirse.

El motor de programación de recursos programa rutas para pedidos de producción planeados y publicados.

El problema de programación del taller de trabajo es un problema combinatorio extremadamente complejo donde el tiempo de solución crece exponencialmente con el número de variables de decisión. Los clientes suelen configurar rutas de producción y datos relacionados de maneras que crean problemas de programación que no se pueden resolver en un tiempo razonable, incluso en hardware moderno. En este artículo se explica el motor de programación y cómo una configuración específica influye en el rendimiento.

Mejore el rendimiento de la programación al reducir la complejidad del problema que resuelve el motor. Algunos de los principales factores que pueden afectar el rendimiento incluyen:

  • Rutas con muchas operaciones
  • Rutas con operaciones en paralelo
  • Operaciones con más de un recurso
  • Operaciones con muchos recursos aplicables
  • Uso de enlaces físicos
  • Uso de la capacidad limitada
  • Número de calendarios diferentes usados
  • Número de espacios de tiempo de trabajo al día en el calendario
  • Duración total de la ruta
  • Ejecución de varios motores de programación en paralelo

Descripción general del flujo de programación básico

Para comprender cómo una configuración determinada afecta al rendimiento, debe saber cómo fluye el proceso dentro del motor y en el código X++ que lo rodea.

El proceso básico de programación de un pedido consta de tres pasos principales:

  • Carga de datos – los modelos de datos X++ se transforman en el modelo de datos interno del motor como tareas y restricciones.
  • Programación : el motor procesa el modelo y las restricciones especificados para generar un resultado. Solicita información de tiempo de trabajo y reservas de capacidad existentes de X++ según sea necesario.
  • Guardar datos: el código X++ procesa el resultado del motor, en forma de ranuras de reserva de capacidad de trabajo, para guardar reservas de capacidad y actualizar las horas de inicio y finalización de los trabajos, las operaciones o el pedido.

Cargar datos en el motor

El motor de programación usa un modelo de datos más abstracto que la base de datos de administración de cadenas de suministros porque es un motor genérico que controla varios orígenes de datos. Los conceptos de ruta, operaciones secundarias y tiempo de ejecución se traducen en el modelo genérico de tareas y restricciones que expone el motor. La lógica para compilar el modelo incluye una lógica de negocios significativa y varía en función de los datos de origen. La clase X++ responsable es WrkCtrScheduler, que incluye clases derivadas para pedidos de producción planeados, pedidos de producción publicados y previsiones del proyecto.

Por ejemplo, considere una ruta que se muestra en la tabla y la imagen siguientes, que es relativamente sencilla.

Oper. N.º Priority Tiempo de preparación Tiempo de ejecución Tiempo en cola posterior Cantidad de recursos Siguiente
10 Principal 1,00 2.00 1 20
10 Secundario 1 1 20
20 Principal 3,00 1,00 3 0

Diagrama de rout de ejemplo.

Al enviar esta ruta al motor, divide la ruta en ocho trabajos, como se muestra en la ilustración siguiente (seleccione la imagen para ampliarla).

Programación de tareas del motor de programación

El vínculo estándar entre dos trabajos es FinishStart, lo que significa que la hora de finalización de un trabajo debe producirse antes de la hora de inicio de otra. El mismo recurso debe realizar la instalación que más adelante controla el proceso, por lo que hay OnSameResource restricciones entre ellos. Entre los trabajos de la operación principal y secundaria relacionados con el lote 10, existen StartStart y FinishFinish vínculos, lo que significa que los trabajos deben iniciar y finalizar al mismo tiempo. Además, hay NotOnSameResource restricciones, que impiden que se use el mismo recurso para las operaciones principales y secundarias.

Para la operación 20, donde la cantidad de recursos se establece en 3, el trabajo de proceso se divide en tres trabajos distintos donde todos los trabajos deben ejecutarse exactamente al mismo tiempo. En este caso, el grupo de rutas está configurado para no reservar capacidad para la cola después de los tiempos programados, por lo que solo existe un trabajo para la cola.

El motor de programación solo entiende los conceptos de los trabajos y no reconoce las operaciones. Esta limitación significa que, durante la programación de operaciones, el sistema divide las operaciones en trabajos, aunque estos trabajos no se conservan en la base de datos.

Para cada trabajo, se define cuál es el requisito de capacidad del trabajo (el número de segundos necesarios). Dependiendo de cómo se definen los requisitos de recursos, también puede enviar, para cada trabajo, una lista de todos los recursos posibles aplicables en los que se puede ejecutar el trabajo y cuál es el requisito de capacidad para ese recurso específico. Aunque se envía la lista de recursos aplicables al compilar el modelo, el motor garantiza que la asignación de recursos permanezca válida durante toda la duración del trabajo.

Programación de componentes internos del motor

Programación de la interfaz del motor

Para comprender cómo funciona el motor internamente, revise la funcionalidad que expone externamente. En X++, la interfaz principal es WrkCtrSchedulerEngineInterface. Tiene los métodos descritos en las siguientes subsecciones.

Motor general

Método propósito
run Programa todos los trabajos cargados y devuelve el código de error.
getJobSchedulingSequenceResult Obtiene el resultado de la programación y el primer trabajo de error para la secuencia identificada por un trabajo específico.
validateJobCapacityReservations Valida las reservas de capacidad para todos los trabajos almacenados por el motor.
setReservationsTimeStamp Envía una marca de tiempo al motor configurado en todas las nuevas reservas de capacidad para los trabajos programados en la memoria caché del motor.
addPropertyToGroupAggregation Agrega un prefijo de propiedad al conjunto de propiedades que se utilizan cuando se agrega capacidad.
addResource Agrega un recurso al grupo de recursos del motor de programación.
addResourceGroup Agrega un grupo de recursos al grupo de recursos del motor de programación.
addResourceGroupMembership Agrega un recurso como miembro de un grupo de recursos.
addOptimizationGoal Agrega un objetivo de optimización de programación (duración o prioridad).

Trabajos individuales

Método propósito
addJobInfo Agrega un registro de información del trabajo que informa al motor sobre un trabajo que debe programarse.
addConstraintJobEndsAt Agrega una restricción de que un trabajo debe finalizar en una fecha y hora específicas.
addConstraintJobStartsAt Agrega una restricción de que un trabajo debe comenzar en una fecha y hora específicas.
addConstraintMaxJobDays Define la restricción que un trabajo puede abarcar durante un número máximo de días especificado.
addConstraintResourceRequirement Agrega la restricción de que el trabajo debe programarse en un recurso específico.
addJobBindPriority Agrega una prioridad de enlace de trabajo para un par (trabajo, nivel de restricción). Un valor de prioridad más alto significa que las variables de trabajo están enlazadas anteriormente. El trabajo se procesa antes de los trabajos con un valor de prioridad inferior en la misma secuencia.
addJobCapacity Agrega información de carga de capacidad para un trabajo (como el tiempo de ejecución del trabajo requerido) independientemente del recurso en el que se ejecuta el trabajo.
addJobResourceCapacity Agrega un recurso al conjunto de recursos que se pueden usar para realizar un trabajo y indica la capacidad necesaria cuando se ejecuta en ese recurso.
addJobGoal Agrega información sobre el objetivo del trabajo para un nivel de restricción específico (hora de finalización más temprana o hora de inicio más tardía).
addJobResourcePriority Agrega la prioridad que se utilizará cuando se programe un trabajo en un recurso.
addJobResourceRuntime Especifica un tiempo de trabajo que depende del recurso en el que está programado el trabajo.
addJobRuntime Especifica un tiempo de trabajo que es independiente del recurso en el que está programado el trabajo.
scheduleJobOnResourceGroup Marca un trabajo para programarlo en el nivel del grupo de recursos.
setJobResourcePreemptionAllowed Establece si se permite la preferencia para un trabajo en un recurso (si el motor puede programar el trabajo en ranuras de capacidad no contiguas).
setRequiredNumberOfResources Establece la cantidad de recursos necesarios para programar un trabajo (solo para la programación de operaciones).

Restricciones entre trabajos

Método propósito
addJobLink Agrega un enlace (como final>inicio) entre dos trabajos.
addConstraintEndsDelayed Define la restricción que un trabajo no puede finalizar antes de que finalicen otros trabajos más un tiempo de retraso.
addConstraintJobListWorkingTimeIntersect Agrega una restricción de que las ranuras de capacidad reservadas para los trabajos deben estar en los horarios de trabajo que se cruzan para los dos recursos utilizados por los trabajos.
addConstraintJobOverlap Agrega una restricción que define cómo se secuencian los trabajos cuando se puede mover una cantidad determinada de un elemento entre dos recursos, mientras que el primer recurso todavía no ha terminado de procesarse, de modo que el segundo recurso pueda empezar a procesarse.
addConstraintNotOnSameResource Añade una restricción de que no se deben programar dos trabajos en el mismo recurso.
addConstraintOnSameResource Agrega una restricción de que dos trabajos no deben usar el mismo recurso.
addJobSameReservations Agrega una restricción de que un trabajo debe terminar teniendo reservas de capacidad para los mismos intervalos de tiempo que el trabajo principal.
setPrimaryParallelJob Agrega información sobre qué trabajo es el trabajo principal en un conjunto de trabajos paralelos.

Solucionador

El motor es un solucionador de restricciones especializado con heurística personalizada. El solucionador se basa en dos elementos principales: variables y restricciones.

Variable

Una variable representa un dominio de valores posibles. El motor de programación tiene dos tipos de variables:

  • Variable DateTime : tiene un dominio de todas las fechas y horas. Puede restringir el dominio acercando los límites inferior y superior del intervalo de tiempo de la variable entre sí.
  • Variable de recurso : tiene un dominio de los recursos aplicables. Puede restringir el dominio eliminando los recursos de la lista.

Restricción

Una restricción actúa en variables mediante la restricción de sus dominios. También depende de las variables, por lo que se activa cuando cambian las variables. El proceso de "propagación de restricciones" es cuando una restricción realiza su función principal e informa a la lógica principal si tiene éxito.

Una variable se considera enlazada cuando no se puede restringir aún más. Para una variable DateTime, esta condición significa que los límites superior e inferior son los mismos. Para la variable Resource, significa que solo tiene un único recurso aplicable. Cuando todas las variables están vinculadas, se encuentra una solución.

Niveles de restricción

Cuando la programación forma parte de la fase de cobertura de planificación de requisitos materiales (MRP), el sistema programa órdenes hacia atrás desde la fecha del requisito. Sin embargo, si el sistema no encuentra un horario que empiece hoy o más tarde y termine antes de la fecha de requisito, cambia la dirección de programación a adelante desde hoy.

El sistema organiza las restricciones en niveles para controlar esta regla de negocio principal. Si el sistema no encuentra una solución al usar las restricciones en el nivel más alto, quita todas las restricciones de ese nivel e intenta el nivel inferior. En la práctica, este proceso significa que, para la programación hacia atrás, el modelo contiene un nivel 1 con objetivos de trabajo de la hora de inicio más reciente dada una restricción de hora de finalización máxima (la fecha del requisito) y un nivel 0 con objetivos de trabajo de la hora de finalización más temprana y dada una restricción mínima de hora de inicio de hoy.

Algoritmo

Los pasos principales del algoritmo del motor son:

  1. Busque secuencias (cadenas de trabajo) que se puedan resolver por separado.
  2. Intente encontrar una solución inicial para la secuencia en el nivel de restricción más alto.
    1. Ordene los trabajos en la secuencia en función del objetivo y las prioridades del trabajo, por lo que el sistema puede encontrar un trabajo de inicio.
    2. Recorra los trabajos en el siguiente orden:
      1. Encuentre todas las restricciones que deben propagarse y ejecute la propagación.
      2. Si todas las variables del trabajo están enlazadas, se encuentra una solución para ese trabajo.
      3. Si una de las variables no se puede enlazar sin infringir las restricciones, revierte el enlace de variables, pruebe un valor diferente en el dominio (para la variable de recurso) y vuelva a ejecutar la propagación de restricciones.
  3. Si no se encuentra ninguna solución, quite todas las restricciones en el nivel de restricción actual, reduzca el nivel de restricción (si hay niveles inferiores disponibles) y vuelva a intentar la búsqueda de soluciones con el nuevo conjunto de restricciones.
  4. Si se encuentra una solución factible, inicie la fase de optimización, que intenta encontrar una mejor solución hasta que se alcance el tiempo de espera de optimización o se agoten todas las combinaciones de recursos.

El solucionador de restricciones no tiene en cuenta los detalles del algoritmo de programación. La "magia" se produce en la definición y combinación de las diversas restricciones.

Determinación de los tiempos de trabajo

Una gran parte de las limitaciones (internas) del motor controla el tiempo de trabajo y la capacidad de un recurso. Básicamente, la tarea consiste en recorrer los intervalos de tiempo de trabajo de un recurso desde un punto determinado en una dirección determinada y encontrar un intervalo suficiente en el que la capacidad necesaria del trabajo (tiempo) pueda ajustarse.

Para hacer esto, el motor necesita conocer los tiempos de trabajo de un recurso. A diferencia de los datos del modelo principal, los tiempos de trabajo se cargan de forma diferida, lo que significa que se cargan en el motor según sea necesario. La razón de este enfoque es que a menudo hay tiempos de trabajo en administración de cadenas de suministros para un calendario durante un período muy largo y normalmente existen muchos calendarios, por lo que los datos serían bastante grandes para cargar previamente.

El motor solicita información del calendario en fragmentos invocando el método WrkCtrSchedulingInteropDataProvider.getWorkingTimesde clase X++. La solicitud es para un ID de calendario específico en un intervalo de tiempo específico. Dependiendo del estado de la caché del servidor en administración de cadenas de suministros, cada una de estas solicitudes podría terminar en varias llamadas a la base de datos, lo que lleva mucho tiempo (en relación con el tiempo computacional puro). Además, si el calendario contiene definiciones de tiempo de trabajo muy elaboradas con muchos intervalos de tiempo de trabajo al día, esta complejidad agrega al tiempo que tarda la carga.

Cuando el motor de programación carga los datos de tiempo de trabajo, conserva estos datos en su caché interno para el calendario específico. Esta retención significa que, si otros trabajos o recursos usan el mismo calendario, las siguientes búsquedas se pueden realizar rápidamente desde la memoria. Una causa común de un rendimiento incorrecto es si se usa un identificador de calendario independiente para cada recurso, ya que los datos se solicitan para cada calendario, aunque el contenido de los calendarios pueda ser el mismo.

Capacidad limitada

Cuando se usa capacidad finita, el sistema divide y reduce las franjas de tiempo de trabajo del calendario en función de las reservas de capacidad existentes. La misma WrkCtrSchedulingInteropDataProvider clase captura estas reservas junto con los calendarios, pero usa el getCapacityReservations método . Al programar durante la planificación maestra, el sistema considera las reservas del plan maestro específico. Si habilita la configuración en la página Parámetros de planeamiento maestro , el sistema también incluye reservas de pedidos de producción firmes. Del mismo modo, al programar un pedido de producción, puede elegir incluir reservaciones de órdenes planificadas existentes, aunque esta secuencia no es tan habitual como la inversa.

La programación tarda más tiempo cuando se usa capacidad finita por varias razones:

  • Capturar la información de capacidad de la base de datos es una operación lenta. Normalmente, el almacenamiento en caché del lado del servidor de la información de capacidad no es tan eficaz como para los horarios de trabajo, porque no se comparte entre recursos como sí lo hacen los calendarios habitualmente.
  • El número de franjas horarias de trabajo a recorrer aumenta debido a las divisiones. Normalmente, el sistema necesita investigar ranuras durante un período de tiempo más largo para poder encontrar una solución.
  • Una vez completada la programación, el sistema debe comprobar si hay reservas en conflicto (consulte la sección "Ejecución de motores de programación en paralelo" para obtener más información).

Examinando las combinaciones de recursos

Si la secuencia de trabajos solo contiene los vínculos estándar FinishStart , lo que significa que forma una cadena simple sin ramas, el sistema puede lograr un resultado óptimo (visto desde el orden único, no entre órdenes) mediante la búsqueda de la mejor solución para el primer trabajo y, a continuación, pasar a encontrar la mejor solución para el siguiente trabajo. La mejor solución para un trabajo es encontrar el recurso que pueda obtener la fecha de inicio y la fecha de finalización del trabajo de manera que más se acerque al objetivo del trabajo (en la programación anticipada esto significa hacer que la fecha de finalización del trabajo sea lo más temprana posible) mientras se respetan las restricciones.

Cuando hay trabajos paralelos, la búsqueda de una solución podría implicar examinar diferentes combinaciones de recursos. El número de posibles combinaciones de recursos es el producto del número de recursos aplicables para los trabajos en paralelo conectados. Especialmente cuando se programa un orden hacia atrás desde una fecha de requisito, la lógica puede tardar bastante tiempo en darse cuenta de que no hay ninguna solución al problema que hará que los trabajos paralelos se ajusten antes de la fecha actual. La lógica debe comprobar todas las combinaciones porque podría haber algunos recursos que tengan una mayor eficacia o un calendario diferente que pueda dar un resultado. Esta condición significa que si no establece un límite de tiempo de espera, el proceso se ejecutará durante mucho tiempo antes de cambiar la dirección hacia adelante.

Esta lógica combinatoria también significa que agregar recursos más aplicables podría hacer que el motor se ejecute más lentamente. Si se producen problemas de rendimiento cuando tiene operaciones paralelas y programación con capacidad infinita, puede corregir parcialmente el problema haciendo que el diseñador de rutas tome una decisión sobre qué recurso se debe usar y, a continuación, asigne el recurso directamente en la operación (porque el motor en la mayoría de los casos siempre termina seleccionando el mismo recurso, por lo que el resultado final es el mismo).

Al establecer el tipo de vínculo entre dos trabajos en difícil, asegúrese de que no haya ningún intervalo de tiempo entre el final de un trabajo y el inicio del siguiente. Esta condición es útil en escenarios en los que el metal se calienta en un trabajo y se procesa en el siguiente, y la refrigeración entre los trabajos no es deseable.

Mediante el uso de enlaces simbólicos estándar y programación de reenvío, si la ruta forma una cadena simple sin ramas, puede lograr un resultado mediante la búsqueda de una solución para el primer trabajo que satisfaga sus propias restricciones y, a continuación, pasar a través de la cadena propagando la hora de finalización del trabajo anterior al siguiente. Si el trabajo actual no encuentra ninguna capacidad, el sistema pospone la hora de inicio, sin afectar a los trabajos anteriores. Esta acción puede crear brechas entre los trabajos. Sin embargo, al utilizar enlaces duros (especialmente en relación con la capacidad finita) para el mismo escenario, el hecho de que un trabajo más adelante en la cadena no pueda encontrar capacidad implica que todos los trabajos anteriores programados deben ser "arrastrados" uno por uno, y por lo tanto, reprogramados varias veces. Especialmente en escenarios con alta carga para varios recursos, los vínculos duros pueden provocar una reacción en cadena en la que los trabajos se afectan entre sí y se deben realizar varias iteraciones antes de que el resultado se estabilice en una programación factible.

Ejecución de motores de programación en paralelo

Al realizar la programación como parte de una ejecución de planificación maestra donde se utilizan auxiliares, cada uno de los hilos auxiliares de planificación maestra puede encargarse de las tareas de programación de órdenes de producción. Este enfoque significa que varios motores de programación se pueden ejecutar al mismo tiempo. Aunque la multithreading proporciona una ventaja de rendimiento significativa, también presenta algunas desventajas funcionales para la programación.

En MRP, el sistema programa todos los pedidos de producción para un determinado nivel de lista de materiales (BOM) en la secuencia de fechas de requisitos. Esta secuencia significa que el sistema programa esos pedidos con la fecha de requisito más antigua en primer lugar, por lo que tienen la mayor probabilidad de obtener la capacidad de recursos disponible. Sin embargo, cuando varios procesadores seleccionan de la lista de pedidos no programados, no se garantiza la secuencia porque un procesador puede terminar su tarea más rápido que otro.

Cuando se programa con capacidad finita y varias instancias del motor, se puede producir una condición de carrera si intenta programar pedidos que usan los mismos recursos al mismo tiempo. El campo Conflictos de planificación de la página de historial de planes maestros registra el número de condiciones de carrera. La lógica de resolución de conflictos sigue estos pasos:

  1. Programe un pedido (sin candados) y obtenga reservas de capacidad.
  2. Tome el bloqueo.
  3. Compruebe si existen reservas de capacidad más recientes para los recursos programados en el intervalo de tiempo.
    • Si no, escriba la capacidad y suelte el bloqueo.
    • Si es así, suelte el candado y reprograme el pedido desde el principio.

Al programar con varias instancias del motor, el resultado no es totalmente determinista porque depende del tiempo exacto de cada subproceso.

Rendimiento de programación de operaciones

La programación de operaciones, también conocida como planificación de capacidad preliminar, puede ser más difícil de resolver desde el punto de vista de un planificador si se usa capacidad finita porque se necesitan más datos para determinar la viabilidad.

La capacidad de un grupo de recursos depende de cuáles y cuántos recursos son miembros del grupo de recursos. Un propio grupo de recursos no tiene ninguna capacidad, solo cuando los recursos son miembros del grupo sí tiene capacidad. Dado que la pertenencia al grupo de recursos puede variar con el tiempo, la capacidad debe evaluarse por día.

En la programación de operaciones, el calendario del grupo de recursos se utiliza para determinar las horas de inicio y finalización de cada operación. Este calendario coloca un límite en el tiempo que puede programar operaciones para una operación en un día en un grupo de recursos. A diferencia del calendario de recursos específicos, los datos de eficiencia del calendario del grupo de recursos se omiten porque solo denota horas de apertura, no capacidad real.

Por ejemplo, si el tiempo de trabajo de un grupo de recursos en una fecha específica es de 8:00 a 16:00, una operación no puede poner más carga en el grupo de recursos que lo que puede caber en 8 horas, independientemente de la capacidad que el grupo de recursos tenga disponible en total en ese día. Sin embargo, la capacidad disponible puede limitar aún más la carga.

La carga de programación de trabajos en todos los recursos del grupo de recursos durante un día determinado se considera al calcular la capacidad disponible para ese día. Para cada fecha, el cálculo es:

Capacidad disponible del grupo de recursos = Capacidad de los recursos del grupo en función de su calendario : carga programada del trabajo en los recursos del grupo - Operaciones programadas en los recursos del grupo : carga programada de operaciones en el grupo de recursos

En la pestaña Requisitos de recursos de la operación de ruta, puede especificar los requisitos de recursos mediante un recurso específico (en cuyo caso la operación se programa mediante ese recurso), un grupo de recursos, un tipo de recurso o una o varias funcionalidades, aptitud, curso o certificado. El uso de todas estas opciones proporciona flexibilidad en el diseño de rutas, pero complica la programación del sistema, ya que se debe tener en cuenta la capacidad por "atributo" (un nombre abstracto usado en el motor para la funcionalidad, las competencias, etc.).

La capacidad del grupo de recursos para una funcionalidad es la suma de la capacidad de todos los recursos del grupo de recursos que tienen la funcionalidad en cuestión. Si un recurso del grupo tiene una funcionalidad, el motor lo considera independientemente del nivel de capacidad necesario.

En la programación de operaciones, la capacidad disponible para una determinada funcionalidad para un grupo de recursos se reduce cuando se carga con una operación que requiere la funcionalidad en cuestión. Si la operación requiere más de una funcionalidad, la capacidad se reduce para todas las funcionalidades necesarias.

Para cada fecha, el cálculo necesario es:

Capacidad disponible para una capacidad = Capacidad para la capacidad − Carga programada del trabajo en los recursos con la capacidad específica, incluidos en el grupo de recursos − Carga programada de operaciones en los recursos con la capacidad específica, incluidos en el grupo de recursos − Carga programada de operaciones en el propio grupo de recursos que requieren la capacidad específica

Si un recurso específico tiene una carga, el motor lo considera al calcular la capacidad disponible del grupo de recursos por funcionalidad, ya que la carga reduce su contribución a la capacidad del grupo, independientemente de si la carga es para esa funcionalidad específica. Si hay carga en el nivel de grupo de recursos, el motor lo considera en el cálculo de la capacidad disponible del grupo de recursos por funcionalidad solo si la carga procede de una operación que requiere la funcionalidad específica.

Esta lógica se aplica a cada tipo de propiedad, por lo que el uso de la programación de operaciones con capacidad finita requiere cargar una cantidad significativa de datos.

Mejorar rendimiento MRP

En el siguiente vídeo de conferencia técnica se proporcionan sugerencias para mejorar el rendimiento de la planificación maestra cuando se usa MRP con el motor de planeamiento maestro en desuso: ¡Ayuda! MRP es lento!

Visualización de la entrada y salida del motor de programación

Para obtener detalles específicos sobre la entrada y salida del proceso de programación, habilite el registro dirigiéndose a Administración de la organización>Configuración>Programación>Puesto de control de rastreo de programación.

En esta página, seleccione Habilitar registro en el panel de acciones y, a continuación, ejecute la programación para el pedido de producción. Cuando termine, regrese a la página Programación de cabina de seguimiento y seleccione Deshabilitar el registro en el Panel de acciones. Actualice la página y aparecerá una nueva línea en la cuadrícula. Seleccione la nueva línea y, a continuación, seleccione Descargar en el panel de acciones. Esta acción proporciona una carpeta comprimida .zip que contiene los siguientes archivos:

  • Log.txt : este archivo de registro describe los pasos que pasa el motor. Es detallado y puede ser abrumador, pero cuando experimentes con la configuración de ruta para resolver problemas de rendimiento, busca la diferencia de tiempo entre la primera y la última línea. Esta diferencia muestra el tiempo exacto que ha invertido el programador.
  • XmlModel.xml : este archivo contiene el modelo integrado en X++ y en el que funciona el motor. El JobId utilizado en el archivo se correlaciona con el RecId de la tabla de origen que contiene los trabajos (ReqRouteJob o ProdRouteJob). En este archivo, compruebe que las fechas de ConstraintJobStartsAt y ConstraintJobEndsAt son las esperadas, la JobGoal propiedad se establece correctamente y los trabajos están relacionados a través de las JobLink restricciones.
  • XmlSlots.xml : este archivo contiene todos los tiempos de trabajo y las reservas de capacidad que solicita el motor. El motor solicita los tiempos de trabajo del calendario y las reservas solo para los períodos en los que intenta colocar los trabajos (más un búfer adicional), por lo que si el archivo contiene un tiempo muy alejado en el futuro, puede ser una indicación de un problema con la configuración. Los ResourceProperty nodos muestran el grupo de recursos y las funcionalidades asociados a cada recurso, junto con los períodos de tiempo pertinentes.
  • Result.xml : este archivo contiene el resultado de la ejecución de programación.

La funcionalidad de seguimiento agrega una sobrecarga de rendimiento significativa, por lo que úsela solo para investigar la programación de pedidos específicos de forma controlada. Si lo activa durante una ejecución de planificación maestra, alcanza rápidamente su límite de tamaño y se detiene.

Resolución de problemas de rendimiento

Como puede ver en las secciones anteriores, algunos problemas en la configuración y el uso del motor de programación pueden provocar problemas de rendimiento. La siguiente lista de comprobación puede ayudarle a solucionar estos problemas. Examine todos los puntos porque a menudo es una combinación de varios factores que conducen a problemas.

Tip

En la tabla siguiente se resumen los problemas de rendimiento de programación de trabajos más comunes y sus soluciones recomendadas. Use los vínculos para ir a las instrucciones detalladas de cada área.

Problema Recomendación Details
No es necesario programar durante el MRP Establecimiento de una barrera de tiempo de capacidad en cero o uso de un plazo de producción estándar Programación como parte de MRP
Demasiados recursos aplicables Asignación de un recurso específico a la operación en tiempo de diseño de ruta Muchos recursos aplicables
Las operaciones paralelas ralentizan la programación Pares de modelos como recursos "virtuales" o exclusión de operaciones que no son cuellos de botella Operaciones paralelas
Cantidad de recursos mayor que una Revise si se necesitan realmente varios recursos para la operación. Cantidad de recursos
Sobrecarga de capacidad finita Usar la opción de cuello de botella y barrera de tiempo separada de capacidad para los recursos de cuello de botella Capacidad limitada
Los vínculos físicos complican la programación Usar vínculos físicos solo cuando sea estrictamente necesario Vínculos físicos
Calendario independiente por recurso Reutilización de calendarios entre recursos tanto como sea posible Calendarios
Muchas franjas horarias por día del calendario Minimizar las franjas horarias de trabajo (por ejemplo, omitir el modelado de pausas de cinco minutos) Intervalos de tiempo
Faltan tiempos de espera de programación o son muy grandes Habilite ambas opciones de tiempo de espera; establecer el tiempo máximo de programación en aproximadamente 30 segundos Tiempos de espera

Realizar la programación como parte de MRP cuando no es necesario

Aunque las rutas se usan con fines de control de producción, como el costeo y los informes, es posible que no necesiten considerarse durante MRP. En algunos casos, tener un tiempo de producción estándar especificado para el artículo será suficiente para la planificación. Establezca la barrera de tiempo de capacidad en cero para desactivar la programación de rutas. Si es necesario programar, establezca cuidadosamente la barrera de tiempo de capacidad porque es posible que las rutas no necesiten considerarse para la extensión completa de la barrera de tiempo de cobertura del MRP.

Si el pedido no está programado durante MRP, en su lugar deberá programarse cuando se firme el pedido planeado. Esto significa que el proceso de reafirmación tomará más tiempo, por lo que dependiendo de cuántos de los pedidos planificados sugeridos se reafirmen, la ganancia de rendimiento durante la MRP podría perderse al reafirmar.

Ruta con operaciones innecesarias

Al diseñar la ruta, evite intentar modelar el mundo real exactamente con todos los pasos que pasa el proceso de producción. Aunque este enfoque puede ser útil en algunos casos, no es bueno para el rendimiento porque el modelo del motor crece más grande (en términos de trabajos y restricciones), y se ejecutan más instrucciones SQL para insertar y actualizar trabajos y reservas de capacidad. Además, existe el efecto subsecuente de tener que informar sobre el progreso de los trabajos eventualmente, lo que las publicaciones automáticas pueden mitigar. Si los datos no se usan para nada, crea una carga innecesaria.

Cree solo las operaciones estrictamente necesarias para la planificación (normalmente recursos de cuello de botella) o para fines de cálculo de costos. En su lugar, agrupe muchas operaciones distintas más pequeñas en una operación mayor que represente una parte mayor del proceso.

Muchos recursos aplicables para una operación

Los requisitos de recursos establecidos en la relación de operación determinan el número de recursos aplicables para una operación. El requisito puede ser para un recurso específico o puede basarse en la pertenencia del recurso en un grupo de recursos o funcionalidad.

Si no usa capacidad finita para programar y todos los recursos aplicables tienen el mismo calendario y eficacia, el motor de programación siempre elige el mismo recurso para una operación, pero solo después de que intente todos los recursos aplicables para comprobar si hay uno que sea mejor que el resto. En este caso, puede reducir considerablemente la carga de la programación asignando siempre un recurso específico a la operación en el tiempo de diseño de la ruta.

Ruta con operaciones en paralelo

Aunque las operaciones paralelas (principal o secundaria) son una herramienta eficaz para modelar escenarios como cuando se necesita una máquina y un operador para realizar una tarea específica, también son el origen de muchos problemas de rendimiento. Si asigna un requisito para un recurso individual específico a la operación principal y secundaria, normalmente no es un problema. Pero si hay muchos recursos posibles para cada una de las operaciones, entonces agrega una complejidad computacional significativa a la programación.

Una alternativa, en lugar de usar operaciones paralelas, es modelar los pares como recursos "virtuales" (que representan al equipo que siempre colabora en las operaciones), o simplemente no modelar una de las operaciones si esta no representa un cuello de botella.

Ruta con cantidad de recursos superior a uno

Si la cantidad de recursos necesarios para una operación es mayor que una, el resultado es eficazmente el mismo que el uso de operaciones principales o secundarias porque se envían varios trabajos paralelos al motor. Sin embargo, en este caso, no se pueden usar asignaciones de recursos específicas porque una cantidad superior a una requiere que se aplique más de un recurso para la operación.

Una operación secundaria que tiene una cantidad de carga de recursos superior a uno significa que se necesita la cantidad especificada de recursos secundarios para cada recurso de la operación principal. Por ejemplo, si una operación principal tiene su cantidad de recursos establecida en dos y su operación secundaria tiene su cantidad de recursos establecida en tres, entonces se necesita un total de seis recursos para la operación secundaria.

Uso excesivo de la capacidad limitada

El uso de capacidad finita requiere que el motor cargue información de capacidad desde una base de datos, lo que puede agregar sobrecarga computacional, especialmente en entornos en los que los recursos se reservan cerca de la capacidad máxima. Como resultado, es importante evaluar cuidadosamente si un recurso realmente necesita usar capacidad finita o se puede sobrerreservar. Dado que puede haber diferencias entre los recursos de capacidad finita en cuanto a su importancia para no sobresaturar, utilice la opción de cuello de botella en un recurso en combinación con un valor independiente en la planificación en "Límite de tiempo de capacidad para los recursos de cuello de botella." El uso del concepto de cuello de botella puede ayudar a reducir el límite de tiempo de capacidad finita general.

El tipo de vínculo estándar de la ruta es suave, lo que permite un intervalo de tiempo entre la hora de finalización de una operación y el inicio del siguiente. Si permite esta brecha, puede hacer que la producción esté inactiva si los materiales o la capacidad no están disponibles para una de las operaciones. Esta situación puede dar lugar a un aumento del trabajo en curso. Este problema no se produce con enlaces duros porque el final y el inicio deben alinearse perfectamente. Sin embargo, establecer vínculos duros dificulta el problema de programación porque el sistema debe calcular el tiempo de trabajo y las intersecciones de capacidad para los dos recursos de las operaciones. Si la programación también implica operaciones paralelas, este requisito agrega un tiempo de cálculo significativo. Si los recursos de las dos operaciones tienen calendarios diferentes que no se superponen en absoluto, el problema no tiene solución.

Use vínculos físicos solo cuando sea estrictamente necesario y considere detenidamente si es necesario para cada operación de la ruta.

Para reducir el trabajo en curso sin aplicar vínculos duros, programe la secuencia dos veces cambiando a la dirección opuesta para la segunda pasada. Si la primera programación se realizó hacia atrás desde la fecha de entrega, la segunda programación debe realizarse a partir de la fecha de inicio programada. Este enfoque comprime los trabajos tanto como sea posible para que el trabajo en curso se minimice.

Calendario separado para cada recurso

Una de las principales fuentes de datos del motor de programación es la información del calendario, que puede resultar costosa de cargar desde la base de datos. Dado que los calendarios se generan en función de las plantillas, puede parecer tentador generar un calendario para cada recurso y, a continuación, ajustar la información de este calendario cuando el recurso tiene tiempo de inactividad y otros problemas. Sin embargo, este enfoque limita gravemente la capacidad del motor de almacenar en caché los datos del calendario porque necesita solicitar nuevos datos para cada recurso. Este enfoque puede causar problemas de rendimiento. Reutilice los calendarios tanto como sea posible entre los recursos y controle los cambios de tiempo de inactividad mediante la asignación de un identificador de calendario diferente durante un período.

Alto número de franjas horarias de trabajo por día de calendario

Dado que el motor funciona mediante el examen de los intervalos de tiempo uno por uno para la capacidad, es beneficioso minimizar el número de intervalos de tiempo por día. Por ejemplo, considere si es importante que la programación resultante refleje que los trabajadores tardan un descanso de cinco minutos cada hora.

Tiempos de espera de programación grandes (o ninguno)

Puede optimizar el rendimiento del motor de programación mediante parámetros que se encuentran en la página Parámetros de programación . Establezca siempre la opción Tiempo de espera de programación habilitada y Tiempo de espera de optimización de programación habilitada en . Si los establece en No, la programación puede ejecutarse infinitamente si se crea una ruta inviable con muchas opciones.

El valor de Tiempo máximo de programación por secuencia controla cuántos segundos se pueden dedicar, como máximo, a tratar de encontrar una solución para una sola secuencia (en la mayoría de los casos, una secuencia corresponde a un solo orden). El valor que se va a usar aquí depende en gran medida de la complejidad de la ruta y la configuración, como la capacidad finita, pero un máximo de aproximadamente 30 segundos es un buen punto de partida.

El valor de Tiempo de espera de los intentos de optimización controla cuántos segundos como máximo se pueden utilizar para encontrar una solución mejor que la que se encontró originalmente. Este valor solo influye en las rutas que usan operaciones paralelas, ya que estas operaciones hacen que sea necesario probar diferentes combinaciones.

Nota:

Los valores establecidos para los tiempos de espera se aplican tanto a la programación de los pedidos de producción publicados como a los pedidos planeados como parte de MRP. Como resultado, establecer valores muy altos puede agregar significativamente al tiempo de ejecución de MRP cuando se ejecuta para un plan con muchos pedidos de producción planeados.

Errores comunes de programación de trabajos

En la tabla siguiente se enumeran los errores conocidos de programación de trabajos con vínculos a información que pueden ayudarle a resolverlos.

Mensaje de error Resolution
El pedido de producción planificado debe programarse antes de poder ser confirmado El pedido de producción planificado debe programarse antes de que pueda ser confirmado
La programación de producción no tiene en cuenta los márgenes de seguridad La programación de producción no tiene en cuenta los márgenes de seguridad
El planeamiento maestro está programando más que la capacidad disponible El planeamiento maestro está programando más que la capacidad disponible
No se pudo encontrar suficiente capacidad No se pudo encontrar suficiente capacidad

Corrige el error del motor de programación "No se pudo encontrar suficiente capacidad"
El valor de retraso no se actualiza cuando se vuelve a programar un pedido planeado. El valor de retraso no se actualiza cuando se vuelve a programar un pedido planeado.