Γρήγορες ενσωματώσεις σε GPUs
Η γρήγορη και ακριβής αναζήτηση είναι ζωτικής σημασίας για ολόκληρη την Perplexity, από την Αναζήτηση και το Computer έως την πλατφόρμα API μας. Στα παρασκήνια, τη βαριά δουλειά κάνουν τα μοντέλα ενσωμάτωσης και κατάταξης, τα οποία βοηθούν τα συστήματά μας να εντοπίσουν τα πιο σχετικά αποτελέσματα για ένα δεδομένο ερώτημα. Επιτυγχάνουμε κατάσταση της
Η γρήγορη και ακριβής αναζήτηση είναι ζωτικής σημασίας για ολόκληρη την Perplexity, από την Αναζήτηση και το Computer μέχρι την πλατφόρμα API μας. Στα παρασκήνια, τη βαριά δουλειά κάνουν τα μοντέλα ενσωμάτωσης και κατάταξης, τα οποία βοηθούν τα συστήματά μας να εντοπίσουν τα πιο σχετικά αποτελέσματα για ένα δεδομένο ερώτημα. Επιτυγχάνουμε ποιότητα και καθυστέρηση αιχμής εκπαιδεύοντας και εξυπηρετώντας τα δικά μας μοντέλα, όπως το pplx-embed.
Αυτό το άρθρο παρουσιάζει μια ματιά στα παρασκήνια της υποδομής εξυπηρέτησης της Perplexity για αυτήν την ειδική κατηγορία μοντέλων. Συζητούμε τις τεχνικές μας για την αποτελεσματική αντιμετώπιση των αναγκών εξαγωγής συμπερασμάτων της αναζήτησης με έμφυτη τεχνητή νοημοσύνη, επιτρέποντας τη γρήγορη δημιουργία πρωτοτύπων και αξιολόγηση μοντέλων, τροφοδοτώντας παράλληλα τον δείκτη αναζήτησης κλίμακας exabyte. Αυτές οι τεχνικές συλλογικά διευρύνουν το σύνορο Pareto ποιότητας και αποδοτικότητας αναζήτησης, επιτρέποντάς μας να εξυπηρετούμε πράκτορες και χρήστες με τα καλύτερα δυνατά αποτελέσματα με το χαμηλότερο δυνατό κόστος και καθυστέρηση.
Ενσωματώσεις για αναζήτηση
Σε μια τυπική ρύθμιση αναζήτησης, τα ευρετηριασμένα έγγραφα χαρτογραφούνται σε έναν διανυσματικό χώρο υψηλών διαστάσεων χρησιμοποιώντας ένα μοντέλο ενσωμάτωσης και αποθηκεύονται σε μια διανυσματική βάση δεδομένων. Με την ενσωμάτωση ενός ερωτήματος με το ίδιο μοντέλο, μπορούν να εντοπιστούν παρόμοια έγγραφα βρίσκοντας τα διανύσματα που βρίσκονται πιο κοντά σε αυτό του ερωτήματος. Αυτό δημιουργεί δύο διαφορετικά μοτίβα κυκλοφορίας για την εξυπηρέτηση ενός μηχανισμού εξαγωγής συμπερασμάτων:
- Μαζική Ενσωμάτωση: κατά την κατασκευή, επέκταση ή επανευρετηρίαση της βάσης δεδομένων, τα μαζικά έγγραφα πρέπει να ενσωματωθούν στον διανυσματικό χώρο, μεγιστοποιώντας την απόδοση για την ελαχιστοποίηση του κόστους.
Μετά την αναζήτηση διανυσμάτων, μεγάλες παρτίδες εγγράφων πρέπει να βαθμολογηθούν, επιτυγχάνοντας μια ισορροπία μεταξύ απόδοσης και καθυστέρησης.
- Online Ενσωμάτωση: κατά την υποβολή ερωτήματος στη βάση δεδομένων, ένα σύντομο ερώτημα πρέπει να ενσωματωθεί για αναζητήσεις, ελαχιστοποιώντας την καθυστέρηση.
Δημιουργήσαμε την υποδομή εξαγωγής συμπερασμάτων μας ώστε να αξιοποιεί όσο το δυνατόν περισσότερα κοινά στοιχεία σε διάφορες περιπτώσεις χρήσης. Δεδομένου ότι συνήθως χρησιμοποιούμε μικρά μοντέλα Transformer για την παραγωγή ενσωματώσεων, μοιραζόμαστε το μεγαλύτερο μέρος της υλοποίησης με τον κώδικα εξαγωγής συμπερασμάτων LLM: οι ενσωματώσεις παρτίδας είναι παρόμοιες με το prefill που δεσμεύεται από υπολογιστικούς πόρους (compute-bound), ενώ οι online ενσωματώσεις, οι οποίες συχνά εκτελούνται σε λίγα tokens, είναι υπολογιστικά παρόμοιες με το decode που δεσμεύется από τη μνήμη (memory-bound). Συνεπώς, επαναχρησιμοποιούμε τα βελτιστοποιημένα kernels prefill και decode για να εξυπηρετήσουμε μοντέλα ενσωμάτωσης. Ως αποτέλεσμα, μπορούμε να επιτύχουμε μαζική απόδοση εξαγωγής συμπερασμάτων παρτίδας με ελάχιστο πρόσθετο μηχανικό έργο, διατηρώντας παράλληλα χαμηλή καθυστέρηση για φόρτους εργασίας online ενσωματώσεων.
Tulips, Roses, and some Ivy
Εκθέτουμε την εξαγωγή συμπερασμάτων μέσω τυποποιημένων API, τόσο εσωτερικά όσο και εξωτερικά μέσω της πλατφόρμας API μας. Στα παρασκήνια, πολλαπλές υπηρεσίες εμπλέκονται στην επεξεργασία ενός αιτήματος ενσωμάτωσης:
- Το Ivy είναι μια πύλη HTTP Rust που καλούν οι υπηρεσίες της Perplexity.
Χειρίζεται την εργασία στην πλευρά της CPU για αιτήματα όπως η ανάλυση JSON, το tokenization, η δημιουργία προτύπων εισόδου και ο διαχωρισμός παρτίδων, μεταφράζοντας τα αιτήματα σε ένα προσαρμοσμένο πρωτόκολλο gRPC για διακομιστές κατάντη (downstream). Αυτός ο διαχωρισμός μας επιτρέπει να διαμορφώνουμε ορισμένες παραμέτρους γύρω από το tokenization και τη μορφοποίηση εισόδου χωρίς να χρειάζεται να αγγίξουμε τις βαρύτερες περιπτώσεις εξαγωγής συμπερασμάτων.
- Το Tulip είναι η διεπαφή διακομιστή εξαγωγής συμπερασμάτων.
Είναι ένας διακομιστής gRPC υλοποιημένος με Rust, tokio και `tonic`. Το Tulip λαμβάνει αιτήματα εξαγωγής συμπερασμάτων gRPC, χειριζόμενο τον προγραμματισμό και τη δημιουργία παρτίδων. Στη συνέχεια, στέλνει τις παρτίδες στον μηχανισμό ROSE, επιστρέφοντας ολοκληρωμένες απαντήσεις στους πελάτες.
Ορίζεται κυρίως σε Python, παρέχοντας kernels, επίπεδα και ορισμούς για μια μεγάλη ποικιλία μοντέλων. Το ROSE υλοποιεί τα περάσματα προς τα εμπρός μέσω μοντέλων, παρέχοντας επίσης διαχείριση γραφημάτων CUDA εξειδικευμένη για ενσωματώσεις. Συνδέεται με το Tulip μέσω μιας συνάρτησης step(), η οποία λαμβάνει μια παρτίδα και επιστρέφει μια αναφορά στον υπολογισμό που εκτελεί στον επιταχυντή.

Δίνοντας προσοχή πέρα από το Kernel
Τόσο τα μοντέλα που βασίζονται σε Transformer όσο και οι υποκείμενες αρχιτεκτονικές Hopper/Blackwell είναι ώριμες τεχνολογίες, επομένως η ενσωμάτωση της εξαγωγής συμπερασμάτων στην πλευρά της GPU έχει συγκεντρωθεί σε μια σε μεγάλο βαθμό βέλτιστη υλοποίηση σε διάφορους μηχανισμούς εξαγωγής συμπερασμάτων. Παρόλα αυτά, ανακαλύψαμε επιπλέον ευκαιρίες βελτίωσης στους χρόνους εκτέλεσης και στα εργαλεία που εκθέτουν τα μοντέλα από άκρο σε άκρο σε έναν πελάτη. Ειδικότερα, διαπιστώσαμε ότι μπορούμε να βελτιώσουμε τις καθυστερήσεις διαχειριζόμενοι προσεκτικά τα γραφήματα CUDA και κατασκευάζοντας μια αφαίρεση LazyTensor για την ασύγχρονη παρακολούθηση ενός αποτελέσματος στην πλευρά της GPU στον εγγενή μηχανισμό Rust. Υλοποιήσαμε αυτά τα χαρακτηριστικά στο Tulip, ώστε να μπορεί να διασυνδεθεί αποτελεσματικά με τις υλοποιήσεις μοντέλων του ROSE.
Tulip
Σχεδιάσαμε το Tulip ώστε να είναι μια όσο το δυνατόν πιο ελαφριά διεπαφή πάνω από την εξυπηρέτηση του μοντέλου μας. Χειρίζεται τα εισερχόμενα αιτήματα σε ασύγχρονες εργασίες Tokio, διατηρώντας μια ομάδα αιτημάτων που παρακολουθεί και από την οποία προγραμματίζει παρτίδες προς αποστολή στον επιταχυντή. Ο μηχανισμός προγραμματισμού στο Tulip είναι πολύ απλός: τα αιτήματα συσσωρεύονται ενώ το Tulip αποστέλλει εργασία ή περιμένει αποτελέσματα. Από τα συσσωρευμένα αιτήματα, οι ακολουθίες επιλέγονται με βάση τη σειρά προτεραιότητας (first-come, first-served) για να εκτελεστούν μέσω του μοντέλου.
Ο απλός μηχανισμός προγραμματισμού υποκινείται από μια παρατήρηση σχετικά με την απόδοση του μοντέλου. Για μικρά μοντέλα ενσωμάτωσης, στα μήκη ακολουθίας που εξυπηρετούμε, παρατηρήσαμε ότι το γραμμικό κόστος των πυκνών επιπέδων κυριαρχεί έναντι του τετραγωνικού κόστος της προσοχής. Επομένως, η καθυστέρηση είναι κυρίως ανάλογη με τον αριθμό των tokens, όχι τον αριθμό των ακολουθιών. Κατά συνέπεια, μόλις μια παρτίδα είναι αρκετά μεγάλη ώστε να κορεστεί η GPU, η οποία είναι γύρω στα 512 tokens σε ένα μοντέλο κάτω του ενός δισεκατομμυρίου παραμέτρων, η συσκευασία περισσότερων ακολουθιών σε αυτήν δεν βελτιώνει την αποδοτικότητα.
Για να διασυνδεθεί αποτελεσματικά με το μοντέλο, το Tulip βασίζεται σε γραφήματα CUDA και παρακολούθηση αποτελεσμάτων lazy για την επικάλυψη εργασιών GPU και CPU και την πλήρη αξιοποίηση των διαθέσιμων πόρων.
Διαχείριση γραφημάτων CUDA
Η εκτέλεση του περάσματος προς τα εμπρός ενός μοντέλου περιλαμβάνει εργασίες τόσο στην πλευρά της CPU όσο και στην πλευρά της GPU. Η CPU είναι υπεύθυνη για τον προγραμματισμό παρτίδων και την εκκίνηση kernels με τις κατάλληλες παραμέτρους, ενώ η GPU εκτελεί τα σχετικά kernels πολλαπλασιασμού πινάκων, προσοχής (attention), κανονικοποίησης (norm) ή ενεργοποίησης. Για φόρτους εργασίας υψηλής απόδοσης, όπως η εκπαίδευση και η εκ νέου ευρετηρίαση, τα γενικά έξοδα της πλευράς της CPU είναι αμελητέα επειδή τα μεγέθη παρτίδων και η καθυστέρηση της πλευράς της GPU είναι και τα δύο μεγάλα. Ωστόσο, σε μικρότερα μεγέθη παρτίδων, η εργασία της πλευράς της CPU μπορεί να υπερισχύσει της εργασίας της πλευράς της GPU.

Για να μετριαστούν τα γενικά έξοδα, αντί να εκκινούνται ανεξάρτητα kernels, μπορεί να κατασκευαστεί ένα γράφημα CUDA για την καταγραφή των μεταδεδομένων που απαιτούνται για την εκκίνηση όλων των kernels ενός περάσματος προς τα εμπρός με μία μόνο κλήση στον οδηγό CUDA. Αυτό εξαλείφει την ανάγκη επανεκτέλεσης δαπανηρού κώδικα Python και PyTorch για τις διαμορφώσεις για τις οποίες μπορούν να καταγραφούν τα γραφήματα CUDA.
Σε κάθε μοντέλο, παρακολουθούμε ένα σημείο καμπής, προσδιορίζοντας τον ελάχιστο αριθμό tokens στον οποίο η εκτέλεση σε GPU είναι πιο δαπανηρή από την εκκίνηση πυρήνα στην πλευρά της CPU. Επειδή τα μοντέλα ενσωμάτωσης είναι μικρά, παρατηρούμε ότι αυτό το σημείο καμπής έρχεται σε παρτίδες χιλιάδων tokens και δεκάδων ακολουθιών. Ορισμένες υλοποιήσεις προσοχής βασίζονται σε δυναμικές εισόδους στην πλευρά του κεντρικού υπολογιστή για τη διαμόρφωση εκκινήσεων πυρήνα, αποτρέποντας τα πλήρη γραφήματα CUDA prefill/dense μοντέλου. Ανεβάσαμε upstream αλλαγές στα σχετικά kernels για να τα ενεργοποιήσουμε στον μηχανισμό εξαγωγής συμπερασμάτων μας.
Για την αντιμετώπιση των γενικών εξόδων, κατασκευάζουμε γραφήματα CUDA ολόκληρου του μοντέλου για όλα τα μοντέλα ενσωμάτωσης και επικαλύπτουμε την εργασία CPU με εργασία GPU. Δεδομένου ότι τα γραφήματα CUDA ελαχιστοποιούν τα γενικά έξοδα της πλευράς της CPU, μόλις εκκινηθεί ένα γράφημα, έχουμε ελεύθερο χρόνο για να ξεκινήσουμε και να βάλουμε στην ουρά την εκτέλεση της επόμενης παρτίδας όποτε είναι διαθέσιμη. Τα αποτελέσματα της εκκρεμούς παρτίδας παρακολουθούνται με ένα LazyTensor, το οποίο επιτρέπει σε μια ασύγχρονη εργασία στη Rust να μπλοκάρει έως ότου ολοκληρωθεί η εκτέλεση της προηγούμενης παρτίδας. Τα γραφήματα CUDA βοηθούν στην εξυπηρέτηση χαμηλής καθυστέρησης διασφαλίζοντας ότι δεν καθυστερούμε από το κόστος εκκίνησης kernels και διευκολύνουν τη βελτιωμένη προγραμματισμού στην περίπτωση υψηλής απόδοσης καθώς ελευθερώνουν την CPU να εργαστεί στην επόμενη παρτίδα νωρίτερα.

Τα γραφήματα CUDA πρέπει να καταγράφονται για κάθε ξεχωριστή διαμόρφωση, γεγονός που για τις ενσωματώσεις σημαίνει ένα γράφημα ανά συνδυασμό μέτρησης ακολουθίας και μέτρησης token. Δεδομένου ότι αυτό το πλέγμα είναι εκτεταμένο, κάνουμε padding στις μετρήσεις token σε κάδος (buckets) που είναι πολλαπλάσια του 64 ή του 256. Αυτό εξακολουθεί να έχει ως αποτέλεσμα χιλιάδες γραφήματα που ενδέχεται να χρειαστούν πολλαπλά λεπτά για να καταγραφούν για ένα τυπικό μοντέλο. Το κόστος της καταγραφής προέρχεται από δύο πηγές: ένα άμεσο πέρασμα προς τα εμπρός που πρέπει να εκτελεστεί για τη μεταγλώττιση kernels και τη ρύθμιση buffers για διάφορα kernels που τα χρειάζονται, ακολουθούμενο από την εκτέλεση καταγραφής που επανεκτελεί κώδικα Python.
Μετριάζουμε το κόστος εκκίνησης καταγράφοντας γραφήματα CUDA lazy καθώς ο μηχανισμός εξυπηρετεί. Παρακολουθούμε κάθε διαμόρφωση και διασφαλίζουμε ότι περνάει από μια άμεση εκτέλεση προθέρμανσης πριν ενεργοποιήσουμε την καταγραφή γραφήματος και την επανάληψη στη δεύτερη επιτυχία. Όλες οι επόμενες εκτελέσεις της ίδιας διαμόρφωσης γραφήματος περνούν στη συνέχεια από επανάληψη γραφήματος CUDA. Η lazy καταγραφή γραφημάτων έχει αντίκτυπο στις καθυστερήσεις p99 κατά την εκκίνηση· ωστόσο, είναι πολύτιμη για τη διασπορά πολλαπλών λεπτών άμεσης εργασίας σε πολλαπλές ώρες. Οι γρηγορότεροι χρόνοι εκκίνησης μας επιτρέπουν να κλιμακώνουμε και να διαχειριζόμαστε καλύτερα τις αναπτύξεις ενσωμάτωσης.
Lazy Tensors
Μέσω της CUDA, η εργασία της GPU είναι ασύγχρονη. Δεδομένου ότι η εκκίνηση ενός kernel ασύγχρονα το τοποθετεί στην ουρά σε μια ροή, ο κώδικας του κεντρικού υπολογιστή πρέπει να συγχρονίζεται ρητά για να διαβάσει τα προκύπτοντα διανύσματα. Για να διευκολυνθεί ένας υψηλότερος βαθμός παραλληλισμού και να είναι δυνατή η εκκίνηση μελλοντικών παρτίδων ενώ περιμένουμε την ολοκλήρωση της προηγούμενης στη συσκευή, βασιζόμαστε σε μια αφαίρεση LazyTensor για την παρακολούθηση τιμών.
Το LazyTensor παρακολουθεί μια μνήμη buffer κεντρικού υπολογιστή σε μνήμη κλειδωμένης σε σελίδα (page-locked) και μια λειτουργία cudaMemcpyAsync μέσω ενός συμβάντος που αντιγράφει δεδομένα από τη συσκευή. Ξεκινά μετά την εκκίνηση του περάσματος προς τα εμπρός στην ίδια ροή (stream). Δεδομένου ότι η λειτουργία αντιγραφής πρέπει να περιμένει την εκτέλεση όλων των προηγούμενων kernels στη ροή, το σχετικό συμβάν παρακολουθεί τόσο την ολοκλήρωση του περάσματος προς τα εμπρός όσο και τη διαθεσιμότητα του αποτελέσματος στην CPU.

Αξιοποιούμε LazyTensors στη μηχανή κωδικοποιητή ROSE για την επικάλυψη εργασιών GPU και CPU. Αντί κάθε κλήση step() να εκτελεί το γράφημα CUDA και να περιμένει να ολοκληρωθεί, η συνάρτηση step() επιστρέφει ένα LazyTensor για την ασύγχρονη παρακολούθηση του αποτελέσματός της. Σε συνδυασμό με τα γραφήματα CUDA, αυτό μας βοηθά να πετύχουμε χαμηλές καθυστερήσεις και καλύτερη απόδοση.

ROSE
Προσαρμόσαμε τον μηχανισμό ROSE, τον οποίο είχαμε αρχικά κατασκευάσει για εξυπηρέτηση LLM, ώστε να χειρίζεται επίσης την εκτέλεση μοντέλων ενσωμάτωσης. Για να ελαχιστοποιηθεί η προσπάθεια που απαιτείται για την υποστήριξη μοντέλων ενσωμάτωσης, το ROSE επαναχρησιμοποιεί επιθετικά κώδικα μεταξύ LLM και ενσωματώσεων. Για παράδειγμα, η εξυπηρέτηση pplx-embed και η αποκωδικοποίηση LLM Qwen3.5 περνούν όλα από τα ίδια kernels. Αυτός ο διαμοιρασμός μας επιτρέπει να εξυπηρετούμε εύκολα ένα μοντέλο ενσωμάτωσης που αρχικά είχε ρυθμιστεί λεπτομερώς (fine-tuned) από ένα LLM για τη δημιουργία πρωτοτύπων, την αξιολόγηση και την εξαγωγή συμπερασμάτων παραγωγής.
Για πυκνά επίπεδα, η ενσωμάτωση και η εξαγωγή συμπερασμάτων LLM είναι πανομοιότυπες, καθώς τα διανύσματα tokens επεξεργάζονται ανεξάρτητα. Στα επίπεδα προσοχής, οι διαφορές αντιμετωπίζονται με την προσθήκη υποστήριξης για ακανόνιστες εισόδους (ragged inputs), μαζί με τις ρυθμίσεις paged prefill και decode που απαιτούνται από τα LLM. Κατά την εξυπηρέτηση ενός μοντέλου ενσωμάτωσης, δεν στιγμιότυπουποιούμε μια κρυφή μνήμη KV (KV cache) και αποστέλλουμε σε παραλλαγές kernels προσοχής που υποστηρίζουν την ακανόνιστη μορφή για την αποφυγή padding. Οι υποστηρικτικές ουσίες μετατροπής και βαθμονόμησης μοιράζονται επίσης με τα LLM.
Ivy
Το Ivy, το επίπεδο διαμεσολαβητή HTTP εξαγωγής συμπερασμάτων μας, παίζει επίσης σημαντικό ρόλο στην απόδοση. Επειδή τα ωφέλιμα φορτία των αιτημάτων ποικίλλουν στην παραγωγή, η δρομολόγηση μεμονωμένων αιτημάτων σε μεμονωμένα αντίγραφα μπορεί να προκαλέσει ανισορροπία φορτίου. Το Ivy χωρίζει τα αιτήματα μεγάλης παρτίδας σε τμήματα και εξισορροπεί το φορτίο μεταξύ των αντιγράφων, βελτιώνοντας την αξιοποίηση και εξομαλύνοντας την καθυστέρηση. Η πρόσφατη εργασία μας σχετικά με τον εσωτερικό tokenizer unigram, πλήρως ανεπτυγμένο στο Ivy, βελτιώνει δραastικά τις καθυστερήσεις σε σύγκριση με τους έτοιμους tokenizers.
...αλλά τα Kernels εξακολουθούν να μετρούν
Το ROSE υποστηρίζει μια ποικιλία υποδομών προσοχής (attention backends). Διαφοերτικά kernels μπορεί να είναι κατάλληλα για συγκεκριμένα μεγέθη προβλημάτων. Με την πάροδο του χρόνου, ενσωματώσαμε τα kernels FlashInfer 2, FlashInfer 3 και FlashAttention 4 για την υλοποίηση ακανόνιστης προσοχής (ragged attention).

Γενικά, παρατηρούμε ότι το FlashAttention 4 είναι ταχύτερο. Ωστόσο, το FlashInfer 3 το ξεπερνά σε μοντέλα που βασίζονται στο Qwen σε πολύ μεγάλα μήκη ακολουθίας. Δεδομένου ότι η απόδοση και η ρύθμιση μπορεί να διαφέρουν ανάλογα με τον αριθμό και τη διάσταση των κεφαλών προσοχής, διατηρούμε την υποστήριξη για πολλαπλές διαμορφώσεις και λαμβάνουμε απόφαση κατά περίπτωση κατά την εξυπηρέτηση.
Benchmarks
Κάνουμε συγκριτική αξιολόγηση (benchmark) έναντι του vLLM v0.22.0, εκτελώντας εξαγωγή συμπερασμάτων σε ακρίβεια BF16 σε πραγματικά βάρη μοντέλων και εισόδους που προέρχονται από σύνολα δεδομένων αξιολόγησης. Όλες οι εκτελέσεις χρονομέτρησης προηγήθηκαν από εκτελέσεις προθέρμανσης που επαλήθευσαν ότι η απόκλιση στην ομοιότητα συνημιτόνου είναι εντός 0,1%.
Ενσωματώσεις χαμηλής καθυστέρησης (p50 / p90 / p99 / μέγ. ms)
Αναφέρουμε χρόνους εκτέλεσης για μέγεθος παρτίδας προ-tokenized αιτημάτων 1, πλήρως διαδοχικά αιτήματα, μήκη ακολουθίας 128, 512 και 4096 tokens.

Βαθμολόγηση χαμηλής καθυστέρησης (p50 / p90 / p99 / μέγ. ms)
Μεγέθη παρτίδων προ-tokenized αιτημάτων 5, 25 και 50, μήκος ακολουθίας 512 tokens.

Ενσωματώσεις υψηλής απόδοσης (emb/s)
Μέγεθος παρτίδας αιτημάτων 100, τέσσερις ταυτόχρονες διεργασίες υποβολής αιτημάτων, μήκη ακολουθίας 512, 1024 και 4096 tokens.

Ενσωματώσεις υψηλής ταυτόχρονης εκτέλεσης (p50 / p90 / p99 / μέγ. ms)
Μήκος ακολουθίας 512, μέγεθος παρτίδας 1, αλλά στέλνουμε 1, 2, 4, 8 και 16 ταυτόχρονα αιτήματα. Αυτό το benchmark περιλαμβάνει επίσης το κόστος tokenization μέσω του Ivy, μαζί με το υπερβολικό κόστος δικτύου μεταξύ Ivy και Tulip.

Συμπέρασμα και μελλοντική εργασία
Η υποδομή εξυπηρέτησης που αποτελείται από τα Ivy, Tulip και ROSE μας επιτρέπει να εξυπηρετούμε ενσωματώσεις για την Perplexity με χαμηλότερη καθυστέρηση και καλύτερη απόδοση, με αποτέλεσμα ακριβέστερη αναζήτηση σε μειωμένο κόστος σε σύγκριση με τις έτοιμες λύσεις.
Εστιάζοντας σε συγκεκριμένα μοντέλα και αναλαμβάνοντας την ευθύνη ολόκληρης της στοίβας, αποκτούμε την απαραίτητη ελευθερία για να επιτύχουμε μια αποτελεσματική ισορροπία μεταξύ απόδοσης και ευελιξίας, συνδυάζοντας εξαιρετικά επαναχρησιμοποιήσιμα και αποδοτικά πρωτογενή στοιχεία Rust παράλληλα με πιο γενικό κώδικα μοντελοποίησης Python. Πολλοί μηχανισμοί εξαγωγής συμπερασμάτων ανοιχτού κώδικα, όπως οι vLLM, SGLang και TokenSpeed, ενσωματώνουν γλώσσες όπως η Rust και η C++ στη στοίβα τους. Έχουμε επενδύσει στη Rust τα τελευταία δύο χρόνια και έχουμε αποκομίσει εξαιρετικά οφέλη τόσο στην απόδοση όσο και στη δυνατότητα συντήρησης. Μοιραζόμενοι το μεγαλύτερο μέρος της υλοποίησης ενσωμάτωσης με τη στοίβα εξυπηρέτησης LLM, απολαμβάνουμε επίσης κέρδη στην απόδοση, χωρίς να απαιτείται η διάθεση σημαντικού μηχανικού κόπου για τη συντήρηση μοντέλων ενσωμάτωσης.
Καθώς τα μοντέλα εξελίσσονται, θα συνεχίσουμε να βελτιώνουμε κάθε επίπεδο της στοίβας μας για να μειώσουμε τις καθυστερήσεις που δεσμεύονται τόσο από την CPU όσο και από την GPU. Τα προσαρμοσμένα πρωτόκολλα που βασίζονται σε gRPC εντός του Ivy και του Tulip μας επιτρέπουν να τροποποιούμε την επικοινωνία για να μειώσουμε τις καθυστερήσεις δικτύου, ενώ το ROSE παρέχει μια βάاة για τη βελτίωση της υπολογιστικής απόδοσης. Επιπλέον, καθώς η υποστήριξη για Python ελεύθερων νημάτων (free-threaded Python) αυξάνεται σε ολόκληρο το οικοσύστημα, θα μπορέσουμε να βελτιώσουμε περαιτέρω τη διαλειτουργικότητα Python-Rust για να μειώσουμε τα γενικά έξοδα.