ByteDance Spark prend en charge la pratique d'inférence de modèle Wanka

Résumé : Cet article est compilé à partir du discours d'ouverture de "ByteDance Spark prend en charge la pratique d'inférence de modèle Wanka" lors de CommunityOverCode Asia 2023 par l'ingénieur en infrastructure ByteDance Liu Chang et l'ingénieur système d'apprentissage automatique ByteDance Zhang Yongqiang.
Dans le processus de développement de la native du cloud, Kubernetes a permis à de plus en plus de types d'applications de charge, y compris le Big Data et l'IA, de migrer vers Kubernetes en raison de ses fortes capacités de construction écologique et de son influence. Byte explore en interne la migration de Spark de Hadoop vers Kubernetes. exécute des tâches cloud natives. L'architecture de gestion des ressources Big Data de ByteDance et l'évolution du déploiement de Spark peuvent être grossièrement divisées en trois étapes :
  • La première étape est la gestion des ressources hors ligne entièrement basée sur YARN. En utilisant YARN à grande échelle pour gérer les clusters Big Data, l'utilisation des ressources Spark peut être efficacement améliorée tout en réduisant les coûts d'exploitation et de maintenance des ressources.
  • La deuxième étape est l'étape de déploiement mixte des ressources hors ligne. En créant un cluster de déploiement hybride de YARN et Kubernetes, l'utilisation globale des ressources hors ligne est encore améliorée. Grâce à la technologie de déploiement hybride, l'utilisation des ressources des clusters et des machines uniques a été considérablement améliorée. Une amélioration plus élevée de l'utilisation des ressources signifie la nécessité de moyens d'isolation plus complets. Par conséquent, nous avons commencé à promouvoir progressivement le déploiement conteneurisé de Spark.
  • La troisième étape est un déploiement cloud natif complet. Les charges hors ligne n'utilisent plus d'architectures différentes pour la gestion, et la pile technologique et le pool de ressources sont véritablement unifiés. La native du cloud de Spark est également progressivement construite et améliorée.
Bien sûr, le cloud natif est une tendance de développement presque unanime dans l'industrie, alors pourquoi utiliser le cloud natif ? Pourquoi utiliser Kubernetes comme base de gestion unifiée des ressources ? Il existe trois avantages principaux : le premier est un fonctionnement et une maintenance efficaces . Kubernetes permet une création et une gestion agiles de charges, qu'il s'agisse de chargement en ligne ou de chargement de données volumineuses, il peut facilement réaliser un développement, une intégration et un déploiement continus. Le deuxième est la mise en commun des ressources .La base unifiée native du Cloud réduit les frais généraux de l'infrastructure et améliore encore l'efficacité du transfert de ressources. En termes d'utilisation des ressources, le taux d'utilisation de l'ensemble du centre de données peut être amélioré de manière plus complète et complète, ce qui augmente l'efficacité. . Le troisième est la prospérité écologique.Nous savons que Kubernetes possède presque l'écosystème le plus actif. Il favorise le développement écologique à tous les niveaux en fournissant des définitions d'interface standardisées, qu'il s'agisse d'installations d'exploitation et de maintenance de base, de gestion d'applications de niveau supérieur ou de réseau et de stockage sous-jacents. . etc., il existe de nombreuses options de gestion qui facilitent l’utilisation native du cloud de Spark.

Échelle ByteDance Spark

ByteDance possède l'échelle commerciale Spark de pointe, exécutant des millions de tâches hors ligne chaque jour, occupant des ressources de millions de cœurs, des dizaines de milliers de cartes GPU et la taille totale du cluster atteint des dizaines de milliers de nœuds. Une charge Spark d’une telle ampleur signifie qu’il n’est pas facile d’implémenter Spark de manière entièrement native. Voici les questions auxquelles nous réfléchissons en pratique. Le déploiement de tâches Spark est-il un déploiement statique par Standalone ou un déploiement dynamique par K8s Native ? Comment implémenter la gestion des ressources au niveau du locataire et le contrôle des tâches Spark sur les K8 ? La gestion doit-elle être effectuée lorsque la tâche est soumise ou lorsque le Pod est créé ? Comment répondre aux besoins de planification de Spark ? Lors de la soumission de tâches dans Spark, le grand nombre de créations de pods provoque-t-il des goulots d'étranglement dans la planification ? Pour une migration d’architecture opérationnelle à si grande échelle, comment pouvons-nous créer des capacités périphériques et fluidifier l’expérience avant et après la migration opérationnelle ?
Au cours du processus d'exploration de la native du cloud par Spark, les partenaires ont également été confrontés à de nombreux problèmes. Les tâches de recherche incluent un grand nombre de tâches de traitement par lots hors ligne avec des exigences GPU extrêmement élevées. Les activités de cluster en ligne peuvent libérer une grande quantité de ressources pendant les faibles pics. les services en ligne ne peuvent pas être pleinement utilisés par le GPU, l'utilisation globale est faible. L'apprentissage automatique est un partenaire important de Spark. Nous résolvons les problèmes ci-dessus et travaillons ensemble pour renforcer l'écosystème environnant. Spark a apporté des améliorations ciblées au moteur pour l'entreprise, et l'entreprise a également bénéficié des ressources, de la planification et de la gestion cloud natives de Spark. .

Solutions natives Spark Cloud et améliorations du moteur

Les méthodes d'utilisation courantes actuelles des solutions technologiques natives du cloud Spark incluent Spark Native et l'opérateur open source Spark de Google. Les deux méthodes atteignent le même objectif et appellent finalement l'outil de ligne de commande Spark-submit. La différence est que Spark Operator de Google prend en charge une sémantique plus riche et injecte des fonctionnalités plus riches plus proches des K8 via Operator et Mutatingwebhook.
Il existe deux solutions technologiques natives du cloud Byte Spark. La première est une migration fluide, qui ne nécessite pas de modifier la méthode de soumission de YARN. Elle est soumise à Kubelet ou Gödel pour la planification via Yodel. soumis au système de planification via Arcee. Les concepts qui doivent être expliqués ici sont les suivants : Gödel est un système de planification de ressources distribué développé par Byte. Il héberge les capacités de planification des ressources de YARN et de Kubernetes et unifie le pool de ressources, les quotas, la planification et l'isolation de Kubernetes et de YARN ; par Byte lui-même. Opérateur qui prend en charge les types de tâches YARN et transforme les composants RM et NM de YARN. Arcee est un opérateur de Big Data unifié natif cloud développé indépendamment par Byte, qui peut gérer plus facilement les charges de Big Data telles que Spark et Flink. La différence entre Yodel et Arcee est que Yodel est une solution Big Data sur Gödel qui est "compatible avec le protocole YARN", tandis qu'Arcee est une solution Big Data sur Gödel qui est "compatible avec le protocole K8s". réutilisera les mêmes technologies Gödel Scheduler et Kubelet.
Cette pratique est un déploiement cloud natif complet, soumis via Arcee Operator. Les capacités de base d'Arcee incluent principalement la gestion du cycle de vie des tâches, la gestion des ressources de tâches et certaines fonctions de personnalisation du moteur.

Introduction à Arcee

L'idée de conception principale d' Arcee est la gestion des tâches à deux niveaux , qui s'appuie sur le modèle de gestion à deux niveaux de YARN - le service de gestion central AM, qui est principalement responsable de la création et de la maintenance des tâches Big Data, puis AM crée et maintient l'informatique. ouvriers. Correspondant au travail Spark, Arcee crée le pilote et le pilote crée l'exécuteur requis. Ce modèle de gestion peut gérer et exprimer efficacement l'état des tâches Big Data et personnaliser les stratégies de gestion des tâches. D'un autre côté, cela peut également garantir que le moteur informatique a un contrôle total sur le fonctionnement des tâches informatiques et a la capacité d'ajuster l'utilisation des ressources selon les besoins.
L'architecture globale est illustrée dans la figure. Arcee Operator contient six modules . Le module Arcee CRD définit deux types de ressources : ArceeApplication et ArceeCommand : ArceeApplication est utilisé pour décrire des tâches spécifiques, et ArceeCommand décrit principalement les opérations utilisées pour les tâches  ; utilisé l'injection et la vérification de la configuration pour l'application/le pod ; Application Manager est responsable de la gestion du cycle de vie des tâches ; PodSetManager est la gestion des ressources de tâches ; EngineManager est la gestion du moteur, utilisée pour implémenter certaines capacités de personnalisation du moteur . pour effectuer des travaux d'interfaçage de Big Data tels que Spark avec des planificateurs par lots.
Le processus complet de soumission de tâches consiste en ce qu'Arnold (plateforme d'apprentissage automatique) lance la soumission de tâches Spark, appelle Spark Client et remplit les paramètres requis pour soumettre la tâche à K8. En mode Arcee, Spark Client utilise le client Arcee intégré pour créer Spark ArceeApplication, qui est prétraitée par Webhook et soumise à APIServer. Ensuite, le contrôleur Arcee reçoit l'événement de création de l'application. L'Arcee ApplicationManager génère le statut de travail correspondant et crée le pilote conformément à la description dans l'application. Le pilote crée les exécuteurs requis à la demande et continuera à surveiller tous les exécuteurs. effectuera également l’injection de configuration associée. Tous les pods du pilote et de l'exécuteur de l'application seront conservés dans le PodsetManager d'Arcee pour les statistiques d'utilisation des ressources et fourniront des informations pertinentes aux autres modules.

Étincelle sur Arcee

Spark sur Arcee peut être considéré dans une certaine mesure comme une amélioration du modèle de déploiement Spark Native. La principale différence est que le client K8s intégré dans le client Spark est remplacé par le composant responsable de la gestion de la charge du pilote. devient opérateur Arcee ; le conducteur et l'exécuteur deviennent indépendants l'un de l'autre. Avoir une application Arcee unifiée pour la maintenance. Arcee assure également la gestion du cycle de vie des tâches, la planification du blindage et d'autres fonctions connexes.

Optimisation du moteur Spark

Sur la base des pratiques commerciales présentées dans la section précédente, le moteur Spark a apporté les améliorations suivantes. Voici l'occurrence et les solutions de chaque problème.
  • L'exécuteur se termine normalement pour éviter les anomalies d'état MPS
      Actuellement, certaines tâches de vidage de la base de données Spark qui nécessitent l'utilisation d'un GPU sont exécutées sur des K8 et mélangées à des services en ligne. Ces tâches partagent le périphérique GPU sur l'hôte via MPS (MPS est la technologie de service multi-processus fournie par Nvidia, qui permet différents processus). processus en même temps. Le processus effectue un multiplexage par répartition spatiale sur le GPU au lieu du multiplexage par répartition temporelle par défaut). Si l'un des multiples processus partagés est tué lors de l'exécution du noyau, il est facile de provoquer une exception fatale au niveau matériel, ce qui entraînera la sortie des autres processus sur le GPU, il est donc nécessaire de gérer la sortie en douceur de chaque processus.
      L'exécution sur des K8 peut entraîner l'expulsion ou la mort du conteneur en raison de l'épuisement des ressources pour certaines raisons de planification. Nous avons soigneusement analysé les situations de sortie de divers exécuteurs et travailleurs des relations entre conducteur, exécuteur, démon et travailleur. En implémentant la sortie gracieuse d'Executor dans l'environnement du conteneur, en capturant le signal de sortie et en effectuant automatiquement cudaDeviceSync, cela empêche MPS d'être dans un état indéfini en raison d'une sortie hors ligne.
  • Résolvez un grand nombre de problèmes de pods en attente via Quota
      Spark prend en charge DynamicAllocation. En utilisation réelle, les utilisateurs définissent généralement Max sur une valeur relativement élevée. Actuellement, afin d'éviter la génération d'un grand nombre de pods en attente, Arnold effectue une vérification du quota basée sur Max uniquement lorsque le quota est suffisant pour démarrer Max. Les exécuteurs peuvent être véritablement soumis aux K8, sinon ils attendent dans la file d'attente du service Arnold. Cependant, l’inconvénient actuel de l’utilisation de Max pour vérifier le quota est qu’il est facile de gaspiller des ressources. S'il y a un quota dans la file d'attente inférieur au maximum, selon les caractéristiques de la tâche en cours, la tâche peut être démarrée en premier pour utiliser les ressources actuelles. Cependant, la logique de vérification du quota actuelle fait que cette partie de la ressource est exécutée. inutilisable et la tâche est toujours mise en file d'attente dans la couche supérieure. Ce problème peut être résolu par les moyens suivants :
    • Utilisez le paramètre Spark.kubernetes.allocation.batch.size pour contrôler le nombre de pods extraits dans chaque lot ;
    • Limitez le nombre maximum de Pening Pods pour une seule tâche via le paramètre Spark.kubernetes.allocation.maxPendingPods ;
    • Cependant, l'ajustement des paramètres ne peut toujours pas résoudre le problème d'un grand nombre de soumissions dans la même file d'attente au même moment. Par conséquent, vous pouvez utiliser Webhook pour vérifier le quota en fonction de la file d'attente. S'il n'y a pas de quota, la création du pod échoue. . Spark gère l'exception, ajoute une stratégie de création de pods, augmente de manière exponentielle l'intervalle de temps de création, etc. pour résoudre ce problème.
  • Optimisation robuste des opérations dans des scénarios de ressources instables sur des sites mixtes
Pour donner quelques exemples, il est souvent constaté que Spark Executor Pod est anormalement rejeté (UnexpectedAdmissionError) lors de plusieurs tests de stress lors de la planification de l'optimisation de la stabilité des ressources. Grâce à une enquête centralisée, plusieurs problèmes de conditions de concurrence dans une série de logiques Kubelet ont été résolus et la ressource mixte quotidienne moyenne a atteint une augmentation stable du taux de remplissage limite. Nous avons également effectué une série de réglages et de transformations, en ajoutant des points de collecte d'indicateurs GPU pour faciliter l'observation de l'utilisation des ressources et en améliorant la tolérance aux pannes de la tâche face à l'instabilité des ressources grâce à des paramètres tels que la liste noire et la spéculation.

Intégration écologique environnante

Dans l'environnement Spark sur K8s, les journaux et les indicateurs de surveillance sont également très importants. Ils peuvent nous aider à observer l'état d'exécution de l'ensemble du cluster, du conteneur et de la tâche, à localiser rapidement les problèmes en fonction des journaux et de la surveillance, et à les gérer en temps opportun. . Par conséquent, un système Trace a été progressivement construit au cours du processus de nativeisation du cloud Spark. Arcee Operator et Gödel Scheduler fournissent des indicateurs de tâches, Spark fournit des indicateurs commerciaux et le composant autonome Metrics Collector fournit des indicateurs de machines physiques et des indicateurs de conteneurs. En termes de journaux, l'agent de journalisation exécuté sur chaque nœud collecte les journaux des chemins spécifiés et les télécharge automatiquement sur la plateforme de journalisation pour analyse et requête. Tous les indicateurs et journaux peuvent être interrogés en temps réel sur la base de la plateforme de formation d'apprentissage automatique Arnold. Des tableaux de données spécifiques sont également fournis. Les utilisateurs peuvent effectuer des requêtes de niveau supérieur en fonction de leurs besoins, telles que la production de rapports, l'optimisation des tâches, la découverte d'anomalies de tâches. etc. . Dans le même temps, Arnold peut également rattraper les mises à jour en temps opportun grâce à la gestion des images.

Pratique du raisonnement sur le modèle Wanka

Nos clusters actuels sont principalement divisés en clusters hors ligne et clusters en ligne. Le cluster hors ligne est principalement axé sur les tâches de formation et se concentre principalement sur le débit des tâches. Il existe des cartes telles que V100, A100 et A800. et se concentre sur la latence et le débit, principalement des cartes plus petites telles que T4, A10 et A30, avec des dizaines de milliers de cartes GPU au total.

contradiction principale

La principale contradiction actuelle est que le quota du cluster hors ligne a été entièrement alloué. Logiquement, les ressources ont été allouées, mais il reste encore beaucoup à améliorer dans l'utilisation globale du cluster hors ligne. De plus, de nombreux besoins informatiques internes ne sont pas satisfaits. Par exemple, notre cluster est comme un grand conteneur. Ces tâches de haute qualité sont en réalité comme des pierres. Les pierres peuvent être pleines, mais il y a encore de nombreux espaces entre les pierres. En fait, beaucoup plus peuvent être comblées. du sable, notre définition du problème est donc de trouver ces lacunes et de les combler avec du sable, c'est-à-dire de trouver des ressources réutilisables appropriées et de proposer des tâches appropriées.

Ressource

Cluster hors ligne : tâches de mauvaise qualité

La première concerne les tâches de faible priorité dans le cluster hors ligne. Cette partie se trouve dans l'ensemble du cluster hors ligne et n'est pas sensible aux retards. Nous utilisons ces ressources inactives avec une faible priorité et planifions des tâches de faible priorité lorsqu'il y a du temps libre. Ensuite, lorsqu’il y aura des tâches hautement prioritaires, elles seront préemptées. En même temps, ce sont les ressources de la carte entière, et leur fourniture n'a pas de règles évidentes, car la soumission hors ligne elle-même n'a pas de règles évidentes et le niveau d'isolement global est relativement faible.

En ligne -> Hors ligne : Marée

L'autre partie concerne les ressources de marée en ligne vers hors ligne. Cette partie nécessite de prêter les ressources inutilisées du cluster en ligne au cluster hors ligne. Nous l'implémentons sur la base de Virtual-Kubelet. Cette partie est également la ressource entière de la carte. aléatoire.Il existe une tendance évidente avec les hauts et les bas de l'activité.Lorsque l'activité en ligne est à son apogée, les ressources sont libérées via une mise à l'échelle automatique, puis prêtées au cluster hors ligne. être à nouveau étendu et le cluster expulsera le pod hors ligne. Il s'agit d'un niveau d'isolation moyen, le pod hors ligne doit s'exécuter sur la même machine, mais la carte peut toujours être isolée.

En ligne->Hors ligne : colocalisation normale

L'autre partie concerne les ressources de colocalisation normales de en ligne à hors ligne. Cette partie signifie en fait que nous prêtons une partie de la puissance de calcul du GPU relativement peu utilisé dans le cluster en ligne au cluster hors ligne. La raison principale est que certains modèles. n'utilisez pas la totalité de la carte et sont vides. La puissance de calcul peut être réutilisée et l'implémentation globale est basée sur Virtual-Kubelet + ByteCUDA + MPS.
ByteCUDA est un hook CUDA auto-développé. Il effectue un travail sur l'isolation de la mémoire et le multiplexage temporel dans la couche supérieure. La couche inférieure MPS améliore le niveau d'isolation global grâce au multiplexage par répartition spatiale. Ce qui est prêté est en fait une ressource de carte non intégrée, c'est-à-dire qu'une carte peut être utilisée à plusieurs fins. Cette carte peut avoir des tâches en ligne et des tâches hors ligne. L'avantage est que le volume d'approvisionnement est relativement stable. Cette partie du service ne s'étend pas ou ne diminue pas automatiquement. Ils fonctionnent tous sur la même carte et ont le niveau d'isolation le plus élevé.
Une grande question que nous nous posons à propos de la colocalisation normale est de savoir comment empêcher le mode hors ligne d'affecter le mode en ligne ? Tout d'abord, l'isolation de la mémoire et l'isolation de la puissance de calcul doivent être effectuées. De plus, nous utilisons un algorithme de prêt dynamique adaptatif à la charge, ou une stratégie de prêt, pour observer une certaine consommation d'énergie du GPU au cours d'une période de fenêtre, puis portons des jugements basés sur cela. ces indicateurs. Nos calculs hors ligne devraient-ils activement éviter les demandes de calcul en ligne afin que le monde en ligne soit moins affecté ?
De plus, MPS est célèbre pour son problème de propagation des erreurs. Le problème mentionné ci-dessus est résolu par une sortie gracieuse. D'après les rendus ci-dessus, nous pouvons voir que le débit en ligne avant et après la colocation est presque inchangé et que le délai augmente d'environ 0,75 ms. En fait, il est acceptable. Son taux d'utilisation est passé de 10 % à l'origine à 70 %. Cela a un faible impact sur les revenus globaux, mais le taux d'utilisation a été grandement amélioré.

Tâche

Après les ressources, ce sont les tâches, c'est ce que nous appelons le sable. La première est que sa demande doit être suffisamment importante, sinon il n'y aura pas besoin de « bidouiller ». De plus, comme il s’agit elles-mêmes de ressources fragmentées, la taille des tâches requises doit être relativement modérée et ne peut pas être particulièrement importante. Il faut également que ces tâches ne puissent pas consommer fortement ces ressources non isolées, comme les disques, les réseaux, etc. De plus, les tâches doivent également pouvoir s'adapter à l'expansion et à la contraction automatique des ressources, car ces ressources sont élastiques ; ressources et doivent être automatiquement utilisées lors de l'expansion des tâches. Les ressources, lorsqu'elles diminuent, ne seront pas gênées par ce rétrécissement.

Tâches de raisonnement hors ligne basées sur Spark

Sur la base des exigences de mise en œuvre ci-dessus, la tâche de raisonnement hors ligne basée sur Spark a finalement été verrouillée. Premièrement, parce qu'il existe un grand nombre d'exigences de raisonnement hors ligne internes, la demande est suffisamment importante et le processus de la tâche de raisonnement est relativement simple ; , et il n'y a rien entre les Executors. Pour les besoins de communication, il n'y a pas besoin de cartes en ligne, de RDMA, etc. de plus, une grande quantité de données est effectivement stockée dans HDFS et Hive, ce qui est naturellement compatible avec Spark ; Dans le même temps, nous devons également utiliser les capacités de traitement et de distribution des données de Spark, ainsi que la capacité d'augmenter et de réduire dynamiquement la capacité en fonction de l'allocation dynamique.

Construction du SDK

Après avoir verrouillé la tâche, nous devons encapsuler autant que possible les meilleures pratiques. Ce qui précède est un diagramme schématique du SDK, qui est une Tide Box qui prend en charge les inférences de modèles courantes telles que Pytorch et Tensorflow, et prend également en charge. Points de contrôle au niveau de la partition. De cette façon, il n'est pas nécessaire de répéter les calculs lorsque les ressources sont retirées, ce qui peut éviter le gaspillage de puissance de calcul et améliorer l'utilisation globale des ressources en prenant en charge le traitement par lots.

Construction de plate-forme

Une fois le SDK construit, la construction de la plate-forme est également un aspect très important. Nous ne voulons pas que les utilisateurs exécutent des commandes directement via Spark Submit, ce qui est peu pratique à contrôler. Par conséquent, la plate-forme d'apprentissage automatique Arnold est utilisée comme base pour gérer ces ressources de manière unifiée. Sur la base du développement et du débogage de Notebook, les variables nécessaires peuvent également être définies à l'avance en une seule étape sans rechercher manuellement Soumettre. . Il est relativement pratique de changer de ressources dans différents scénarios en même temps. Également plus flexible.
De plus, la méthode de démarrage des tâches peut prendre en charge plusieurs méthodes telles que le déclenchement d'événements en amont, le déclenchement de synchronisation, le déclenchement d'API, etc., ce qui facilite l'utilisation par l'utilisateur. Par exemple, si vous souhaitez organiser certaines exigences d'automatisation du pipeline ou des utilisateurs, vous pouvez les mettre en œuvre de manière flexible grâce à ces méthodes. De plus, l'exploitation et la maintenance des tâches sont également très importantes. Il permet de visualiser les tâches historiques et de revenir en arrière sur les problèmes en un seul clic.

Correspondance tâche-ressource

Il existe de nombreux types de tâches d'inférence Spark. L'une est la demande d'urgence soudaine. Cette partie de la demande de ressources est relativement importante, le temps est également urgent et il s'agit généralement d'une demande non conventionnelle. Pour cette partie, nous devons utiliser une faible optimisation hors ligne. et Tide est une ressource dotée de cartes plus complètes et d'une puissance de calcul plus forte. De plus, il est nécessaire de revenir en arrière par lots sur les tâches qui nécessitent des réexécutions régulières, qui nécessitent des ressources relativement importantes et ont une urgence de tâche moyenne, et d'utiliser ces ressources dans des déploiements mixtes courants et normaux. Les tâches de routine peuvent être quotidiennes et nécessiter des ressources moyennes. Nous utiliserons un approvisionnement relativement plus stable et plus stable de ressources de colocalisation normales pour les prendre en charge.
L'état maximal du prêt en ligne au prêt hors ligne est d'environ 10 000+ GPU Tidal ; le déploiement mixte normal est d'environ 20 000+. Cette partie est également due au déploiement mixte hors ligne, l'utilisation globale a doublé, il y a environ 100+ tâches d'inférence hors ligne chacune. jour, et une seule La tâche a une limite maximale de 5K+ GPU. Nous limitons activement cette partie, sinon les utilisateurs peuvent l'augmenter encore plus, ce qui entraînera l'occupation de toutes les ressources. Une tâche de brossage de base de données typique nécessite des ressources stables pour s'exécuter pendant 9,5 jours. Grâce à cette ressource élastique, l'horaire a été réduit à 7,5 heures.

perspectives d'avenir

À l'avenir, nos ressources de colocalisation flexibles devront faire davantage, non seulement pour améliorer l'utilisation globale des ressources, mais également pour optimiser l'ensemble des ressources. Premièrement, essayez d'éviter l'impact sur les opérations en ligne, afin qu'il puisse être davantage utilisé hors ligne et atteindre un taux d'utilisation plus élevé. De plus, nous devons encore connecter davantage d'entreprises pour augmenter l'échelle globale et améliorer les performances globales. et en même temps réduire ou éviter autant que possible les problèmes liés causés par une restauration inutile des ressources.
Un camarade de poulet "open source" deepin-IDE et a finalement réalisé l'amorçage ! Bon gars, Tencent a vraiment transformé Switch en une « machine d'apprentissage pensante » Examen des échecs de Tencent Cloud le 8 avril et explication de la situation Reconstruction du démarrage du bureau à distance RustDesk Client Web La base de données de terminal open source de WeChat basée sur SQLite WCDB a inauguré une mise à niveau majeure Liste d'avril TIOBE : PHP est tombé à un plus bas historique, Fabrice Bellard, le père de FFmpeg, a sorti l'outil de compression audio TSAC , Google a sorti un gros modèle de code, CodeGemma , est-ce que ça va vous tuer ? C'est tellement bon qu'il est open source - outil d'édition d'images et d'affiches open source
{{o.name}}
{{m.nom}}

Je suppose que tu aimes

Origine my.oschina.net/u/5941630/blog/10581528
conseillé
Classement