Maison  >  Article  >  Périphériques technologiques  >  Modèle Bytedance déploiement à grande échelle combat réel

Modèle Bytedance déploiement à grande échelle combat réel

王林
王林avant
2023-04-12 20:31:041050parcourir

Modèle Bytedance déploiement à grande échelle combat réel

1. Introduction au contexte

Dans ByteDance, les applications basées sur l'apprentissage profond fleurissent partout. Alors que les ingénieurs se concentrent sur les effets de modèle, ils doivent également prêter attention à la cohérence et aux performances des services en ligne. Cela nécessite généralement une division du travail entre des experts en algorithmes et des experts en ingénierie. Ce mode entraîne des coûts relativement élevés, tels que le dépannage et la vérification des différences.

Avec la popularité du framework PyTorch/TensorFlow, la formation des modèles d'apprentissage en profondeur et le raisonnement en ligne ont été unifiés. Les développeurs n'ont qu'à prêter attention à la logique de l'algorithme spécifique et à appeler l'API Python du framework pour terminer le processus de vérification de la formation. , le modèle peut être facilement exporté et le travail de raisonnement est complété par un moteur C++ unifié hautes performances. Expérience développeur améliorée, de la formation au déploiement.

Cependant, un service complet comporte généralement de nombreuses logiques métier telles que le pré-traitement/post-traitement. Ce type de logique traite généralement diverses entrées dans des Tensors, puis les entre dans le modèle. traités au format Target, certains scénarios typiques sont les suivants :

  • Bert
  • Resnet

Modèle Bytedance déploiement à grande échelle combat réel

Modèle Bytedance déploiement à grande échelle combat réel

Notre objectif est de fournir des solutions de formation et d'inférence automatisées et unifiées pour le processus de bout en bout ci-dessus, et atténuer le développement manuel du processus d'inférence, des différences d'alignement et d'autres problèmes pour obtenir une solution de déploiement unifiée à grande échelle.

2. Problèmes fondamentaux

PyTorch/TensorFlow et d'autres frameworks ont relativement résolu le problème de la formation/inférence de modèle unifié, de sorte que le calcul du modèle lui-même n'a pas le problème de l'intégration de la formation et de l'inférence (l'optimisation des performances de l'opérateur n'est pas dans le cadre de cette discussion).

Le problème principal à résoudre est le suivant : le pré-traitement et le post-traitement doivent fournir une formation performante et une solution intégrée push.

Pour ce type de logique, TensorFlow 2.x fournit tf.function (pas encore complet) et PyTorch fournit TorchScript, qui, sans exception, sélectionne un sous-ensemble de la syntaxe Python native. Mais même si elle est si puissante, il reste des problèmes qui ne peuvent être ignorés :

  • Performance : La plupart de cette solution est basée sur l'implémentation de machines virtuelles. La solution de machine virtuelle est flexible et très contrôlable, mais la plupart des machines virtuelles sont en deep learning. les frameworks n’ont généralement pas de performances suffisantes. En complément, le cadre a été conçu pour l'informatique Tensor au début. Le coût de chaque opérateur dans l'informatique matricielle est très élevé et le coût de répartition et de planification des machines virtuelles peut être ignoré. Cependant, les frais généraux liés au portage vers un langage de programmation sont difficiles à ignorer, et écrire trop de code deviendra un goulot d'étranglement en termes de performances. Selon les tests, les performances de l'interpréteur TorchScript ne représentent qu'environ 1/5 de celles de Python, et les performances de tf.function sont encore pires.
  • Fonctions incomplètes : en fait, lorsqu'elles sont appliquées à des scénarios réels, nous pouvons encore trouver de nombreuses fonctions importantes que tf.function/TorchScript ne prend pas en charge. Par exemple : les ressources personnalisées ne peuvent pas être empaquetées et ne peuvent sérialiser que les types intégrés ; uniquement lors du traitement des octets, Unicode comme le chinois provoquera des différences ; le conteneur doit être isomorphe et ne prend pas en charge les types personnalisés, etc...

De plus, il existe de nombreuses tâches d'apprentissage non approfondies, comme il y en a encore beaucoup tâches d'apprentissage non approfondies dans le traitement du langage naturel Les applications ou sous-tâches d'apprentissage profond, telles que l'étiquetage de séquences, le décodage de modèles de langage, la construction de caractéristiques artificielles de modèles arborescents et d'autres tâches, ont généralement des paradigmes de fonctionnalités plus flexibles, mais en même temps, elles ont Une solution intégrée de formation et de push de bout en bout n'a pas été entièrement mise en œuvre. Il reste encore beaucoup de travail de développement et de vérification de l'exactitude.

Afin de résoudre les problèmes ci-dessus, nous avons développé une solution de prétraitement basée sur la compilation : MATXScript !

3. MATXScript

Dans le développement d'algorithmes d'apprentissage profond, les développeurs utilisent généralement Python pour des itérations et des expérimentations rapides, tout en utilisant C++ pour développer des services en ligne hautes performances, dans lesquels la vérification de l'exactitude et le développement de services deviendront un fardeau plus lourd !

MatxScript (https://github.com/bytedance/matxscript) est un compilateur AOT pour le sous-langage Python, qui peut traduire automatiquement Python en C++ et fournir des fonctions d'empaquetage et de publication en un clic. L'utilisation de MATXScript permet aux développeurs d'itérer rapidement sur les modèles tout en déployant des services hautes performances à moindre coût.

L'architecture de base est la suivante :

Modèle Bytedance déploiement à grande échelle combat réel

  • La couche la plus basse est une bibliothèque de base pure C++/CUDA, développée par des experts opérateurs hautes performances.
  • En plus de la bibliothèque de base, la bibliothèque Python est encapsulée selon la convention et peut être utilisée dans le processus de formation.
  • Lorsque l'inférence est nécessaire, MATXScript peut être utilisé pour traduire le code Python en code C++ équivalent, le compiler dans une bibliothèque de liens dynamiques, ajouter le modèle et d'autres ressources dépendantes, puis le conditionner et le publier ensemble.

Parmi eux, le rôle du compilateur est très critique, et son processus principal est le suivant :

Modèle Bytedance déploiement à grande échelle combat réel

Grâce au processus ci-dessus, le code de prétraitement écrit par l'utilisateur peut être compilé dans un JitOp dans le Pipeline, afin de relier le pré- et post-traitement au modèle, nous avons également développé un système de traçage (le design de l'interface fait référence à PyTorch), avec l'architecture suivante :

Modèle Bytedance déploiement à grande échelle combat réel

Basé sur MATXScript, nous pouvons utiliser le même ensemble de code pour la formation et l'inférence, ce qui réduit considérablement le coût de déploiement du modèle. Dans le même temps, l'architecture et l'algorithme sont découplés et les étudiants en algorithme peuvent travailler entièrement en Python. Les étudiants en architecture se concentrent sur le développement du compilateur et l'optimisation du runtime. Dans ByteDance, cette solution a été vérifiée par un déploiement à grande échelle !

4. Un petit test

Ici, nous prenons le prétraitement de texte anglais le plus simple comme exemple pour montrer comment utiliser MATXScript.

Objectif : convertir un morceau de texte anglais en index

  1. Écrire une logique de recherche de dictionnaire de base
class Text2Ids:
def __init__(self) -> None:
self.table: Dict[str, int] = {
"hello": 0,
"world": 1,
"[UNK]": 2,
}

def lookup(self, word: str)
return self.table.get(word, 2)

def__call__ (self, words: List[str])
return [self.lookup(w) for w in words]
  1. Write Pipeline
import matx

class WorkFlow:
def __init__(self):
# 此处会进行代码编译,Python 代码自动编译封装为 Callable 对象
self.text2ids = matx.script(Text2Ids)()

def process(self, texts):
ids = self.text2ids(texts)
return ids

# test
handler = WorkFlow()
print(handler.process("hello world unknown"))
# output: [0, 1, 2]
  1. Tracer l'exportation sur le disque
# dump
mod = matx.trace(handler.process, "hello world")
print(mod.run({"texts": "hello world"}))
mod.save('./my_dir')
# load
mod = matx.load('./my_dir', -1)
print(mod.run({"texts": "hello world"}))
  1. C++ Load
#include <string>
#include <vector>
#include <map>
#include <iostream>
#include <matxscript/pipeline/tx_session.h>
using namespace ::matxscript::runtime;
int main()
{
// test case
std::unordered_map<std::string, RTValue> feed_dict;
feed_dict.emplace("texts", Unicode(U"hello world"));
std::vector<std::pair<std::string, RTValue>> result;
const char* module_path = "./my_dir";
const char* module_name = "model.spec.json";
{
// -1 mean cpu
auto sess = TXSession::Load(module_path, module_name, -1);
auto result = sess->Run(feed_dict);
for (auto& r : result) {
std::cout << "key: " << r.first << ", value: " << r.second << std::endl;
}
}
return 0;
}

Terminez le le code peut être trouvé sur : https://github.com/bytedance/matxscript/tree/main/examples/text2ids

Résumé : Ce qui précède est une logique de prétraitement très simple implémentée en Python pur et peut être chargée par un C++ général. code Run, combinons le modèle pour montrer un véritable cas multimodal de bout en bout !

5. Cas multimodal

Ici, nous prenons comme exemple le multimodal graphique et textuel (Bert+Resnet). Le modèle est écrit à l'aide de PyTorch pour montrer le travail réel de formation et de déploiement.

  1. Configurer l'environnement
    a. Configurer l'infrastructure telle que gcc/cuda (généralement les étudiants en exploitation et maintenance l'ont déjà fait)
    b Installer MATXScript et les bibliothèques de base développées sur cette base (texte, vision, etc.)
  2. . Écrivez le code du modèle
    a. Il est omis ici. Vous pouvez vous référer à des articles ou à d'autres implémentations open source pour le faire vous-même
  3. Écrivez le code de prétraitement

a.

a. TextPipeline peut être utilisé comme une classe Python normale. Connectez-vous simplement à l'ensemble de données

b VisionPipeline implique un prétraitement GPU et est plus adapté au traitement par lots. Vous devez construire un DataLoader séparément (enterrez un point ici, nous ouvrirons la source. DataLoader multithread interne de ByteDance plus tard)

    Ajouter Téléchargez le code du modèle et commencez la formation

  1. Exportez le modèle d'inférence de bout en bout
  2. from typing import List, Dict, Tuple
    import libcut
    import matx
    class Vocabulary:
    ...
    def utf8_decoder(s: List[bytes]):
    return [x.decode() for x in s]
    class TextNDArrayBuilder:
    ...
    class TextPipeline:
    def __init__(self, mode: str = "eval"):
    self.mode = mode
    self.cut_engine = libcut.Cutter('/path/to/cut_models', ...)
    self.vocab = matx.script(Vocabulary)('/path/to/vocab.txt')
    self.decoder = matx.script(utf8_decoder)
    self.input_builder = matx.script(TextNDArrayBuilder)(self.vocab)
    def process(self, text: List[bytes]):
    # List[bytes] 是对齐 C++ 的 vector<string>
    text: List[str] = self.decoder(text)
    words: List[List[str]] = self.cut_engine(text)
    batch_ids: List[List[int]] = self.vocab(words)
    input_ids, segment_ids, mask_ids = self.input_builder(batch_ids, 32)
    if self.mode == "train":
    return input_ids.torch(), segment_ids.torch(), mask_ids.torch()
    return input_ids, segment_ids, mask_ids
  3. Résumé : Après les étapes ci-dessus, nous pouvons terminer la formation de bout en bout & release work, et l'ensemble du processus est complété avec du code Python pur et peut être entièrement complété par les étudiants en algorithme qui le contrôlent eux-mêmes. Bien entendu, s'il existe des problèmes de performances dans le calcul du modèle lui-même, celui-ci peut également être effectué en coulisse grâce à la modification et à l'optimisation automatiques de l'image.
  4. Remarque : pour des exemples de code complets, voir https://github.com/bytedance/matxscript/tree/main/examples/e2e_multi_modal
6 Unified Server

Dans le dernier chapitre, nous avons obtenu un package modèle publié par un. étudiant en algorithme , ce chapitre explique comment charger et exécuter à l'aide d'un service unifié.

Le serveur complet comprend : le protocole IDL, la stratégie de traitement par lots, la planification et la disposition des threads/threads, le raisonnement du modèle...

Ici, nous discutons uniquement du raisonnement du modèle, et le reste peut être développé comme convenu. Nous utilisons une fonction principale pour illustrer le processus de chargement et d'exécution du modèle :

from typing import List, Dict, Tuple
import matx
from matx import vision
class VisionPipeline:
def __init__(self,
 device_id: int = 0,
 mode: str = "eval",
 image_size: int = 224,):
self.is_training = mode == 'train'
self.mode = mode
...
def process(self, image,):
if self.is_training:
decode_nds = self.random_crop_decode(image)
flip_nds = self.random_flip(decode_nds)
resize_nds = self.resize(flip_nds)
transpose_nd = self.transpose_norm(resize_nds, vision.SYNC)
else:
decode_nds = self.decode(image)
resize_nds = self.resize(decode_nds)
crop_nds = self.center_crop(resize_nds)
transpose_nd = self.transpose_norm(crop_nds, vision.SYNC)
if self.mode == "trace":
return transpose_nd
return transpose_nd.torch()

Le code ci-dessus est le cas le plus simple de chargement d'un modèle multimodal en C++. Pour les étudiants qui développent des serveurs, il leur suffit de créer des abstractions et des conventions simples. Le code ci-dessus peut être transformé en un framework de service de modèle C++ unifié.

VII. Plus d'informations

Nous sommes l'équipe du système d'apprentissage automatique Bytedance-AML, engagée à fournir à l'entreprise un cadre intégré unifié de formation et de promotion de haute performance, et à servir également la coopération via la plateforme d'apprentissage automatique Volcano Engine Pour entreprises, la plate-forme d'apprentissage automatique Volcano Engine devrait fournir un support lié à MATX à partir de 2023, y compris des environnements miroir prédéfinis, des échantillons publics de scénarios courants, un support technique lors de l'accès et de l'utilisation en entreprise, etc., ce qui permet d'obtenir une formation et une inférence à faible coût. scénarios. Effets d’accélération et d’intégration. Bienvenue pour en savoir plus sur nos produits sur https://www.volcengine.com/product/ml-platform.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer