GPU-তে দ্রুত এম্বেডিংস

এই নিবন্ধটি এই বিশেষ শ্রেণীর মডেলগুলোর জন্য Perplexity-এর সার্ভিং অবকাঠামোর ভেতরের একটি দৃশ্য উপস্থাপন করে।

লেখকগণPerplexity Engineering

অনুসন্ধান এবং কম্পিউটার থেকে শুরু করে আমাদের API প্ল্যাটফর্ম পর্যন্ত Perplexity-এর সমস্ত বিষয়ের জন্যই দ্রুত এবং নিখুঁত অনুসন্ধান অত্যন্ত গুরুত্বপূর্ণ। পর্দার আড়ালে, ভারী কাজটি করে এম্বেডিং এবং র‍্যাঙ্কিং মডেলগুলি, যা আমাদের সিস্টেমগুলিকে নির্দিষ্ট কোয়েরির জন্য সবচেয়ে প্রাসঙ্গিক ফলাফল শনাক্ত করতে সাহায্য করে। pplx-embed-এর মতো আমাদের নিজস্ব মডেল তৈরি এবং পরিবেশন করার মাধ্যমে আমরা সর্বাধুনিক গুণমান এবং লেটেন্সি অর্জন করি।

এই নিবন্ধটি এই বিশেষ শ্রেণীর মডেলগুলির জন্য Perplexity-এর সার্ভিং অবকাঠামোর ভেতরের একটি দৃশ্য উপস্থাপন করে। AI-নিয়েটিভ অনুসন্ধানের ইনফারেন্সের প্রয়োজনীয়তাগুলিকে দক্ষতার সাথে সমাধান করার জন্য আমাদের কৌশলগুলি নিয়ে আমরা আলোচনা করি, যা আমাদের exabyte-scale search index-কে চালিত করার সাথে সাথে মডেলগুলির দ্রুত প্রোটোটাইপিং এবং মূল্যায়ন সক্ষম করে। এই কৌশলগুলি সম্মিলিতভাবে অনুসন্ধান গুণমান এবং দক্ষতার প্যারেটো সীমানাকে প্রসারিত করে, যা আমাদের সর্বনিম্ন খরচে এবং লেটেন্সিতে এজেন্ট এবং ব্যবহারকারীদের সর্বোত্তম সম্ভাব্য ফলাফল পরিবেশন করতে সক্ষম করে।

অনুসন্ধানের জন্য এম্বেডিংস

একটি সাধারণ সার্চ সেটআপে, ইনডেক্স করা নথিগুলোকে একটি এম্বেডিং মডেল ব্যবহার করে উচ্চ-মাত্রিক ভেক্টর স্পেসে ম্যাপ করা হয় এবং একটি ভেক্টর ডাটাবেসে সংরক্ষণ করা হয়। একই মডেল ব্যবহার করে একটি কোয়েরিকে এম্বেড করলে, কোয়েরিটির সবচেয়ে কাছাকাছি ভেক্টরগুলো খুঁজে নিয়ে অনুরূপ নথি শনাক্ত করা যায়। এর ফলে একটি ইনফারেন্স ইঞ্জিনের জন্য পরিবেশন করতে দুটি ভিন্ন ট্রাফিক প্যাটার্ন তৈরি হয়:

  • ব্যাচ এম্বেডিং: ডাটাবেস তৈরি, সম্প্রসারণ বা পুনরায় ইনডেক্স করার সময়, বিপুল নথি ভেক্টর স্পেসে এম্বেড করতে হয়, যাতে খরচ কমাতে থ্রুপুট সর্বাধিক হয়.

ভেক্টর অনুসন্ধানের পরে, থ্রুপুট এবং লেটেন্সির মধ্যে একটি ভারসাম্য বজায় রেখে বড় ব্যাচের নথিগুলিকে স্কোর করতে হয়।

  • অনলাইন এম্বেডিং: ডেটাবেস অনুসন্ধান করার সময়, লুকআপের জন্য একটি ছোট কোয়েরি এম্বেড করতে হয়, যা লেটেন্সি কমিয়ে দেয়।

ইউজ কেস জুড়ে যতটা সম্ভব সাধারণ উপাদান ব্যবহার করার জন্য আমরা আমাদের ইনফারেন্স অবকাঠামো তৈরি করেছি। যেহেতু আমরা সাধারণত এম্বেডিং তৈরি করতে ছোট Transformer মডেল ব্যবহার করি, তাই আমরা আমাদের LLM ইনফারেন্স কোডের সাথে বাস্তবায়নের সিংহভাগ অংশ শেয়ার করি: ব্যাচ এম্বেডিং কম্পিউট-বাউন্ড প্রফিল-এর মতো, অন্যদিকে অনলাইন এম্বেডিং, যা প্রায়শই কয়েকটি টোকেনে চলে, তা গণনার দিক থেকে মেমোরি-বাউন্ড ডিকোড-এর অনুরূপ। তাই আমরা এম্বেডিং মডেল পরিবেশন করতে আমাদের অপ্টিমাইজড প্রফিল এবং ডিকোড কার্নেল পুনরায় ব্যবহার করি। ফলস্বরূপ, অনলাইন এম্বেডিং কাজের চাপের জন্য কম লেটেন্সি বজায় রেখে, আমরা ন্যূনতম অতিরিক্ত ইঞ্জিনিয়ারিং কাজের মাধ্যমে বিশাল ব্যাচ ইনফারেন্স থ্রুপুট অর্জন করতে পারি।

Tulips, Roses এবং কিছু Ivy

আমরা অভ্যন্তরীণভাবে এবং আমাদের API প্ল্যাটফর্মের মাধ্যমে বাহ্যিকভাবে, মানসম্মত API-এর মাধ্যমে ইনফারেন্স প্রকাশ করি। পর্দার আড়ালে, একটি এম্বেডিং অনুরোধ প্রক্রিয়াকরণে একাধিক পরিষেবা জড়িত থাকে:

  • Ivy হলো একটি Rust HTTP গেটওয়ে যা Perplexity পরিষেবাগুলি কল করে।

এটি JSON পার্সিং, টোকেনাইজেশন, ইনপুট টেমপ্লেটিং এবং ব্যাচ স্প্লিটিংয়ের মতো অনুরোধগুলির জন্য CPU-side কাজ পরিচালনা করে এবং ডাউনস্ট্রিম সার্ভারগুলির জন্য একটি কাস্টম gRPC প্রোটোকলে অনুরোধগুলি অনুবাদ করে। এই পৃথকীকরণ আমাদের ভারী ইনফারেন্স ইনস্ট্যান্সগুলি স্পর্শ না করেই টোকেনাইজেশন এবং ইনপুট ফরম্যাটিংয়ের চারপাশে নির্দিষ্ট প্যারামিটার কনফিগার করতে দেয়।

  • Tulip হলো ইনফারেন্স সার্ভার ইন্টারফেস।

এটি একটি gRPC সার্ভার যা Rust, tokio, এবং tonic দিয়ে তৈরি। Tulip gRPC ইনফারেন্স অনুরোধ গ্রহণ করে এবং শিডিউলিং ও ব্যাচিং পরিচালনা করে। এরপর এটি ব্যাচগুলোকে ROSE ইঞ্জিনে পাঠায় এবং ক্লায়েন্টদের কাছে সম্পন্ন প্রতিক্রিয়া ফিরিয়ে দেয়।

  • ROSE (Runtime-Optimized Serving Engine) মডেল ইনফারেন্স বাস্তবায়ন করে।

এটি মূলত Python-এ সংজ্ঞায়িত, যা বিভিন্ন ধরনের মডেলের জন্য কার্নেল, লেয়ার এবং সংজ্ঞা প্রদান করে। ROSE মডেলগুলির মাধ্যমে ফরওয়ার্ড পাস বাস্তবায়ন করে, এমনকি এম্বেডিংয়ের জন্য বিশেষায়িত CUDA গ্রাফ পরিচালনাও প্রদান করে। এটি একটি step() ফাংশনের মাধ্যমে Tulip-এর সাথে যুক্ত থাকে, যা একটি ব্যাচ নেয় এবং এটি অ্যাকিলারেটরে যে গণনা সম্পাদন করে তার একটি রেফারেন্স প্রদান করে।

এম্বেডিং অনুরোধের জন্য মডেল-সার্ভিং আর্কিটেকচার, GPU-তে ROSE চালানো Ivy থেকে Tulip সার্ভার পর্যন্ত।

কার্নেলের বাইরেও মনোযোগ দেওয়া

Transformer-ভিত্তিক মডেল এবং অন্তর্নিহিত Hopper/Blackwell আর্কিটেকচার উভয়ই পরিপক্ক প্রযুক্তি, তাই জিপিইউ সাইডে এম্বেডিং ইনফারেন্স বিভিন্ন ইনফারেন্স ইঞ্জিনের মধ্যে একটি অত্যন্ত অপ্টিমাইজড বাস্তবায়নের রূপ নিয়েছে। তা সত্ত্বেও, আমরা রানটাইম এবং হার্নেসগুলিতে উন্নতির অতিরিক্ত সুযোগ খুঁজে পেয়েছি যা মডেলগুলিকে এন্ড-টু-এন্ড ক্লায়েন্টের সামনে নিয়ে আসে। বিশেষ করে, আমরা দেখতে পেয়েছি যে CUDA গ্রাফ সাবধানে পরিচালনা করে এবং নেটিভ Rust ইঞ্জিনে জিপিইউ-সাইড ফলাফল অ্যাসিঙ্ক্রোনাসভাবে ট্র্যাক করার জন্য একটি LazyTensor অ্যাবস্ট্রাকশন তৈরি করে আমরা লেটেন্সি উন্নত করতে পারি। আমরা Tulip-এ এই বৈশিষ্ট্যগুলি বাস্তবায়ন করেছি, যাতে এটি ROSE-এর মডেল বাস্তবায়নের সাথে কার্যকরভাবে ইন্টারফেস করতে পারে।

Tulip

আমরা Tulip-কে আমাদের মডেল সার্ভিংয়ের উপর যথাসম্ভব হালকা একটি ইন্টারফেস হিসেবে ডিজাইন করেছি। এটি Tokio অ্যাসিঙ্ক্রোনাস টাস্কে ইনকামিং অনুরোধগুলি পরিচালনা করে, এটি যে অনুরোধগুলি ট্র্যাক করে তার একটি পুল বজায় রাখে এবং অ্যাকিলারেটরে ডিসপ্যাচ করার জন্য সেগুলির ব্যাচ শিডিউল করে। Tulip-এ শিডিউলিং মেকানিজমটি খুবই সহজ: Tulip যখন কাজ ডিসপ্যাচ করছে বা ফলাফলের জন্য অপেক্ষা করছে তখন অনুরোধগুলি জমা হতে থাকে। জমাকৃত অনুরোধগুলি থেকে, মডেলের মাধ্যমে চালানোর জন্য ফার্স্ট-কাম, ফার্স্ট-সার্ভড ভিত্তিতে সিকোয়েন্সগুলি বেছে নেওয়া হয়।

মডেল পারফরম্যান্সের উপর একটি পর্যবেক্ষণের দ্বারা সহজ শিডিউলিং মেকানিজমটি অনুপ্রাণিত হয়েছে। ছোট এম্বেডিং মডেলগুলির জন্য, আমরা যে সিকোয়েন্স লেংথগুলিতে সার্ভ করি, তাতে আমরা লক্ষ্য করেছি যে অ্যাটেনশনের কোয়াড্রেটিক খরচের চেয়ে ডেন্স লেয়ারের লিনিয়ার খরচ বেশি প্রভাবশালী। সুতরাং, লেটেন্সি মূলত সিকোয়েন্সের সংখ্যার চেয়ে টোকেন সংখ্যার সমানুপাতিক। ফলস্বরূপ, একবার একটি ব্যাচ জিপিইউ স্যাচুরেট করার মতো যথেষ্ট বড় হলে (যা এক বিলিয়নের কম প্যারামিটারের মডেলের ক্ষেত্রে প্রায় ৫১২ টোকেন), সেটিতে আরও সিকোয়েন্স প্যাক করা কার্যকারিতা উন্নত করে না।

মডেলের সাথে কার্যকরভাবে ইন্টারফেস করতে, Tulip জিপিইউ এবং সিপিইউ-এর কাজ ওভারল্যাপ করতে এবং উপলব্ধ রিসোর্সগুলি সম্পূর্ণরূপে ব্যবহার করতে CUDA গ্রাফ এবং লেজি রেজাল্ট ট্র্যাক করার উপর নির্ভর করে।

CUDA গ্রাফ ম্যানেজমেন্ট

একটি মডেলের ফরওয়ার্ড পাস চালাতে CPU-পার্শ্ব এবং GPU-পার্শ্ব—দুই ধরনের কাজই লাগে। ব্যাচ নির্ধারণ করা এবং উপযুক্ত প্যারামিটারসহ কার্নেল চালু করার দায়িত্ব CPU-এর, আর প্রাসঙ্গিক ম্যাট্রিক্স গুণ, অ্যাটেনশন, নর্ম বা অ্যাক্টিভেশন কার্নেলগুলো চালায় GPU। প্রশিক্ষণ এবং রিইনডেক্সিং-এর মতো উচ্চ-থ্রুপুট ওয়ার্কলোডে CPU-পার্শ্বের ওভারহেড নগণ্য, কারণ ব্যাচের আকার এবং GPU-পার্শ্বের লেটেন্সি—দুটিই বড়। তবে ছোট ব্যাচ সাইজে CPU-পার্শ্বের কাজ GPU-পার্শ্বের কাজকে ছাড়িয়ে যেতে পারে.

CUDA গ্রাফ ছাড়া একটি ফরোয়ার্ড পাসের সময় CPU ও GPU এক্সিকিউশন।

ওভারহেড প্রশমিত করতে, স্বাধীন কার্নেল চালু করার পরিবর্তে, CUDA ড্রাইভারের একক কল সহ একটি ফরওয়ার্ড পাসের সমস্ত কার্নেল চালু করার জন্য প্রয়োজনীয় মেটাডেটা ক্যাপচার করতে একটি CUDA গ্রাফ তৈরি করা যেতে পারে। এটি যে কনফিগারেশনগুলির জন্য CUDA গ্রাফ ক্যাপচার করা যায় সেগুলির জন্য ব্যয়বহুল Python এবং PyTorch কোড পুনরায় চালানোর প্রয়োজনীয়তা দূর করে।

প্রতিটি মডেল জুড়ে, আমরা একটি ইনফ্লেকশন পয়েন্ট ট্র্যাক করি, যা টোকেনের ন্যূনতম সংখ্যা নির্ধারণ করে যেখানে জিপিইউ এক্সিকিউশন সিপিইউ-সাইড কার্নেল লঞ্চের চেয়ে বেশি ব্যয়বহুল। যেহেতু এম্বেডিং মডেলগুলি ছোট, তাই আমরা দেখতে পাই যে এই ইনফ্লেকশন পয়েন্টটি হাজার হাজার টোকেন এবং কয়েক ডজন সিকোয়েন্সের ব্যাচে আসে। কিছু অ্যাটেনশন বাস্তবায়ন কার্নেল লঞ্চ কনফিগার করার জন্য গতিশীল হোস্ট-সাইড ইনপুটের উপর নির্ভর করে, যা পূর্ণ-মডেল প্রফিল/ডেন্স CUDA গ্রাফগুলিকে বাধাগ্রস্ত করে। আমাদের ইনফারেন্স ইঞ্জিনে প্রাসঙ্গিক কার্নেলগুলি সক্ষম করতে আমরা সেগুলিতে পরিবর্তন আপস্ট্রিম করেছি।

ওভারহেড সমাধান করার জন্য, আমরা সমস্ত এম্বেডিং মডেলের জন্য সম্পূর্ণ-মডেল CUDA গ্রাফ তৈরি করি এবং GPU কাজের সাথে CPU কাজ ওভারল্যাপ করি। যেহেতু CUDA গ্রাফ CPU-side ওভারহেড কমিয়ে দেয়, একবার একটি গ্রাফ চালু হলে, পরবর্তী ব্যাচ উপলব্ধ হওয়ার সাথে সাথে সেটির এক্সিকিউশন শুরু এবং কিউতে যুক্ত করার মতো ফাঁকা সময় আমাদের থাকে। অপেক্ষমাণ ব্যাচের ফলাফলগুলি একটি LazyTensor-এর সাথে ট্র্যাক করা হয়, যা পূর্ববর্তী ব্যাচ এক্সিকিউশন শেষ না হওয়া পর্যন্ত Rust-এর একটি অ্যাসিঙ্ক্রোনাস টাস্ককে ব্লক করতে দেয়। CUDA গ্রাফগুলি কার্নেল লঞ্চের খরচের কারণে আমাদের আটকে না থাকা নিশ্চিত করে লো-লেটেন্সি সার্ভিংয়ে সাহায্য করে এবং হাই-থ্রুপুট ক্ষেত্রে উন্নত শিডিউলিং সহজতর করে কারণ এগুলি CPU-কে পরবর্তী ব্যাচে দ্রুত কাজ করার জন্য মুক্ত করে।

CUDA গ্রাফসহ একটি ফরোয়ার্ড পাসের সময় CPU ও GPU এক্সিকিউশন।

প্রতিটি স্বতন্ত্র কনফিগারেশনের জন্য CUDA গ্রাফ অবশ্যই ক্যাপচার করতে হবে, যার অর্থ এম্বেডিংয়ের জন্য প্রতিটি সিকোয়েন্স কাউন্ট এবং টোকেন কাউন্ট সমন্বয়ের জন্য একটি গ্রাফ। যেহেতু এই গ্রিডটি বিস্তৃত, তাই আমরা টোকেন কাউন্টগুলিকে ৬৪ বা ২৫৬-এর গুণিতক বালতিতে প্যাড করি। এর ফলে এখনও হাজার হাজার গ্রাফ তৈরি হয় যা একটি সাধারণ মডেলের জন্য ক্যাপচার করতে কয়েক মিনিট সময় নিতে পারে। ক্যাপচারের খরচ দুটি উৎস থেকে আসে: একটি ইগার ফরওয়ার্ড পাস যা কার্নেল কম্পাইল করতে এবং বিভিন্ন কার্নেলের জন্য বাফার সেটআপ করতে অবশ্যই এক্সিকিউট করতে হবে, তারপরে ক্যাপচার রান যা Python কোড পুনরায় এক্সিকিউট করে।

ইঞ্জিন সার্ভ করার সাথে সাথে আমরা অলসভাবে (lazily) CUDA গ্রাফ ক্যাপচার করে স্টার্টআপ খরচ কমিয়ে দিই। আমরা প্রতিটি কনফিগারেশন ট্র্যাক করি এবং নিশ্চিত করি যে গ্রাফ ক্যাপচার ট্রিগার করার এবং দ্বিতীয় হিটে রিপ্লে করার আগে এটি একটি ইগার ওয়ার্মআপ রানের মধ্য দিয়ে যায়। একই গ্রাফ কনফিগারেশনের পরবর্তী সমস্ত এক্সিকিউশন তখন CUDA গ্রাফ রিপ্লে-র মাধ্যমে যায়। স্টার্টআপের সময় লেজি গ্রাফ ক্যাপচারের p99 লেটেন্সির উপর প্রভাব পড়ে; তবে, একাধিক ঘণ্টা জুড়ে কয়েক মিনিটের ইগার কাজ ছড়িয়ে দেওয়ার ক্ষেত্রে এটি মূল্যবান। দ্রুত স্টার্টআপের সময় আমাদের এম্বেডিং মোতায়েনগুলিকে আরও ভালোভাবে স্কেল এবং পরিচালনা করতে সাহায্য করে।

লেজি টেনসর

CUDA-র মাধ্যমে, জিপিইউ কাজ অ্যাসিঙ্ক্রোনাস হয়। যেহেতু একটি কার্নেল অ্যাসিঙ্ক্রোনাসভাবে চালু করা এটিকে একটি স্ট্রিমে কিউতে যুক্ত করে, তাই ফলস্বরূপ ভেক্টরগুলি পড়ার জন্য হোস্ট কোডটিকে স্পষ্টভাবে সিঙ্ক্রোনাইজ করতে হবে। উচ্চ মাত্রার সমান্তরালতা সহজতর করার জন্য এবং ডিভাইসে পূর্ববর্তীটির সম্পূর্ণ হওয়ার জন্য অপেক্ষা করার সময় ভবিষ্যতের ব্যাচগুলি শুরু করতে সক্ষম হওয়ার জন্য, আমরা মানগুলি ট্র্যাক করতে একটি LazyTensor অ্যাবস্ট্রাকশনের উপর নির্ভর করি।

LazyTensor পেজ-লকড মেমরিতে একটি হোস্ট বাফার এবং ডিভাইস থেকে ডেটা কপি করার একটি ইভেন্টের মাধ্যমে একটি cudaMemcpyAsync অপারেশন ট্র্যাক করে। এটি একই স্ট্রিমে ফরওয়ার্ড পাস চালু হওয়ার পরে শুরু হয়। যেহেতু কপি অপারেশনটিকে স্ট্রিমের পূর্ববর্তী সমস্ত কার্নেল এক্সিকিউট করার জন্য অপেক্ষা করতে হয়, তাই সংশ্লিষ্ট ইভেন্টটি ফরওয়ার্ড পাসের সমাপ্তি এবং CPU-তে ফলাফলের উপলব্ধতা উভয়ই ট্র্যাক করে।

CUDA গ্রাফ লঞ্চ থেকে অ্যাসিনক্রোনাস কপি ও সিঙ্ক্রোনাইজেশন পর্যন্ত LazyTensor এক্সিকিউশন।

জিপিইউ এবং সিপিইউ-এর কাজ ওভারল্যাপ করার জন্য আমরা আমাদের ROSE এনকোডার ইঞ্জিনে LazyTensor ব্যবহার করি। প্রতিটি step() কল CUDA গ্রাফ চালানো এবং সেটির সমাপ্তির জন্য অপেক্ষা করার পরিবর্তে, step() এর ফলাফল অ্যাসিঙ্ক্রোনাসভাবে ট্র্যাক করতে একটি LazyTensor ফিরিয়ে দেয়। CUDA গ্রাফের সাথে মিলিত হয়ে, এটি আমাদের কম লেটেন্সি এবং উন্নত থ্রুপুট অর্জনে সহায়তা করে।

ক্রমাগত GPU ব্যাচগুলোর সাথে CPU প্রস্তুতি ও সিঙ্ক্রোনাইজেশন ওভারল্যাপ করা।

ROSE

আমরা আমাদের ROSE ইঞ্জিনকে মানানসই করেছি, যা আমরা মূলত LLM সার্ভিংয়ের জন্য তৈরি করেছিলাম, যাতে এটি এম্বেডিং মডেলগুলির এক্সিকিউশনও পরিচালনা করতে পারে। এম্বেডিং মডেলগুলিকে সমর্থন করার জন্য প্রয়োজনীয় প্রচেষ্টা কমাতে, ROSE LLM এবং এম্বেডিংয়ের মধ্যে আক্রমণাত্মকভাবে কোড পুনরায় ব্যবহার করে। উদাহরণস্বরূপ, pplx-embed সার্ভিং এবং Qwen3.5 LLM ডিকোড উভয়ই একই কার্নেলের মধ্য দিয়ে যায়। এই শেয়ারিং আমাদের প্রোটোটাইপিং, মূল্যায়ন এবং প্রোডাকশন ইনফারেন্সের জন্য মূলত একটি LLM থেকে ফাইন-টিউন করা একটি এম্বেডিং মডেলকে সহজে পরিবেশন করতে দেয়।

ডেন্স লেয়ারের জন্য, টোকেন ভেক্টরগুলি স্বাধীনভাবে প্রসেস হওয়ায় এম্বেডিং এবং LLM ইনফারেন্স অভিন্ন হয়। অ্যাটেনশন লেয়ারে, LLM-গুলির দ্বারা প্রয়োজনীয় পেজড প্রফিল এবং ডিকোড সেটআপের পাশাপাশি র‍্যাগড ইনপুটের জন্য সমর্থন যোগ করে পার্থক্যগুলি পরিচালনা করা হয়। কোনো এম্বেডিং মডেল পরিবেশন করার সময়, আমরা KV ক্যাশ ইনস্টাংশিয়েট করি না এবং প্যাডিং এড়ানোর জন্য র‍্যাগড ফরম্যাট সমর্থন করে এমন বিভিন্ন অ্যাটেনশন কার্নেলে ডিসপ্যাচ করি। সহায়ক রূপান্তর এবং ক্যালিব্রেশন রুটিনগুলিও LLM-গুলির সাথে শেয়ার করা হয়।

Ivy

আমাদের ইনফারেন্স HTTP প্রক্সি লেয়ার, Ivy, পারফরম্যান্সেও একটি গুরুত্বপূর্ণ ভূমিকা পালন করে। উৎপাদনে অনুরোধের পে-লোড পরিবর্তিত হওয়ায়, পৃথক রেপ্লিকায় পৃথক অনুরোধ রাউট করলে লোড ভারসাম্যহীনতা সৃষ্টি হতে পারে। Ivy বড়-ব্যাচের অনুরোধগুলিকে চাঙ্কে বিভক্ত করে এবং রেপ্লি‌কাগুলির মধ্যে লোড-ব্যালেন্স করে, যা ব্যবহার বৃদ্ধি করে এবং লেটেন্সিকে মসৃণ করে। Ivy-তে সম্পূর্ণরূপে রোল আউট করা ইন-হাউস ইউনিগ্রাম টোকেনাইজেশন সংক্রান্ত আমাদের সাম্প্রতিক কাজ, অফ-দ্য-শেল্ফ টোকেনাইজারগুলির তুলনায় লেটেন্সিকে নাটকীয়ভাবে উন্নত করে।

...তা সত্ত্বেও কার্নেলগুলি গুরুত্বপূর্ণ

ROSE বিভিন্ন ধরনের অ্যাটেনশন ব্যাকএন্ড সমর্থন করে। বিভিন্ন কার্নেল নির্দিষ্ট সমস্যার আকারের জন্য উপযুক্ত হতে পারে। সময়ের সাথে সাথে, আমরা র‍্যাগড অ্যাটেনশন বাস্তবায়নের জন্য FlashInfer 2, FlashInfer 3 এবং FlashAttention 4 কার্নেলগুলিকে সংহত করেছি।

বিভিন্ন মডেল কনফিগারেশন ও সমস্যা আকার জুড়ে অ্যাটেনশন-কর্ণেলের কর্মক্ষমতা।

সাধারণত, আমরা দেখতে পাই যে FlashAttention 4 দ্রুততর। তবে, খুব দীর্ঘ সিকোয়েন্স লেংথের ক্ষেত্রে Qwen-ভিত্তিক মডেলগুলিতে FlashInfer 3 এটিকে ছাড়িয়ে যায়। যেহেতু পারফরম্যান্স এবং টিউনিং অ্যাটেনশন হেডের সংখ্যা ও মাত্রার সাথে পরিবর্তিত হতে পারে, তাই আমরা একাধিক কনফিগারেশনের জন্য সমর্থন বজায় রাখি এবং সার্ভ করার সময় কেস-বাই-কেস ভিত্তিতে সিদ্ধান্ত নিই।

বেন্চমার্কস

আমরা vLLM v0.22.0-এর সাথে তুলনা করে বেন্চমার্ক করি, যেখানে মূল্যায়ন ডেটাসেট থেকে প্রাপ্ত প্রকৃত মডেল ওজন এবং ইনপুটের উপর BF16 নির্ভুলতায় ইনফারেন্স চালানো হয়। সমস্ত টাইমিং রান-এর পূর্বে ওয়ার্মআপ রান পরিচালিত হয়েছিল যা যাচাই করে যে কোসাইন সাদৃশ্যের বিচ্যুতি ০.১%-এর মধ্যে রয়েছে।

লো-লেটেন্সি এম্বেডিংস (p50 / p90 / p99 / max ms)

আমরা প্রি-টোকেনাইজড অনুরোধের ব্যাচ সাইজ ১, সম্পূর্ণ সিকোয়েন্সিয়াল অনুরোধ এবং ১২৮, ৫১২ ও ৪০৯৬ টোকেন সিকোয়েন্স লেংথের জন্য রানটাইম রিপোর্ট করি।

128, 512, এবং 4096 টোকেনের সিকোয়েন্স দৈর্ঘ্যে প্রি-টোকেনাইজড, ধারাবাহিক-অনুরোধ এমবেডিং লেটেন্সি বেঞ্চমার্ক, যেখানে অনুরোধ ব্যাচ সাইজ 1।

লো-লেটেন্সি স্কোরিং (p50 / p90 / p99 / max ms)

প্রি-টোকেনাইজড অনুরোধের ব্যাচ সাইজ ৫, ২৫ এবং ৫০, সিকোয়েন্স লেংথ ৫১২ টোকেন।

সিকোয়েন্স দৈর্ঘ্য 512-এ প্রি-টোকেনাইজড, ধারাবাহিক-অনুরোধ স্কোরিং লেটেন্সি বেঞ্চমার্ক, যেখানে অনুরোধ ব্যাচ সাইজ 5, 25, এবং 50।

হাই-থ্রুপুট এম্বেডিংস (emb/s)

অনুরোধের ব্যাচ সাইজ ১০০, অনুরোধ জমা দিচ্ছে এমন চারটি সমকালীন প্রসেস এবং সিকোয়েন্স লেংথ হলো ৫১২, ১০২৪ ও ৪০৯৬ টোকেন।

512, 1024, এবং 4096 টোকেনের সিকোয়েন্স দৈর্ঘ্যে এমবেডিং থ্রুপুট, যেখানে অনুরোধ ব্যাচ সাইজ 100 এবং চারটি সমান্তরাল প্রসেস।

হাই-কনকারেন্সি এম্বেডিংস (p50 / p90 / p99 / max ms)

সিকোয়েন্স লেংথ ৫১২, ব্যাচ সাইজ ১, তবে আমরা ১, ২, ৪, ৮ এবং ১৬টি সমকালীন অনুরোধ পাঠাই। এই বেন্চমার্কে Ivy এবং Tulip-এর মধ্যে নেটওয়ার্কিং ওভারহেডের পাশাপাশি Ivy-এর মাধ্যমে টোকেনাইজেশনের খরচও অন্তর্ভুক্ত রয়েছে।

সমকালীন অনুরোধ সংখ্যার জুড়ে এমবেডিং লেটেন্সি, যার মধ্যে Ivy টোকেনাইজেশন এবং Ivy–Tulip নেটওয়ার্কিং ওভারহেড অন্তর্ভুক্ত।

উপসংহার এবং ভবিষ্যৎ কাজ

Ivy, Tulip এবং ROSE-এর সমন্বয়ে গঠিত সার্ভিং অবকাঠামো আমাদের Perplexity-এর জন্য কম লেটেন্সি এবং উন্নত থ্রুপুটে এম্বেডিং পরিবেশন করতে সক্ষম করে, যার ফলে অফ-দ্য-শেল্ফ সমাধানের তুলনায় হ্রাসকৃত খরচে আরও নিখুঁত অনুসন্ধান পাওয়া যায়।

নির্দিষ্ট মডেলগুলিতে ফোকাস করে এবং পুরো স্ট্যাকের মালিকানা গ্রহণ করে, আমরা পারফরম্যান্স এবং নমনীয়তার মধ্যে একটি কার্যকর ভারসাম্য বজায় রাখার জন্য প্রয়োজনীয় স্বাধীনতা অর্জন করি, যেখানে অত্যন্ত পুনঃব্যবহারযোগ্য এবং পারফর্ম্যান্ট Rust প্রিমিটিভগুলিকে আরও জেনেরিক Python মডেলিং কোডের পাশাপাশি মিশ্রিত করা হয়। vLLM, SGLang, এবং TokenSpeed-এর মতো অনেক ওপেন সোর্স ইনফারেন্স ইঞ্জিন তাদের স্ট্যাকে Rust এবং C++ এর মতো ভাষাগুলিকে সংহত করছে। আমরা গত দুই বছরে Rust-এ বিনিয়োগ করেছি এবং পারফরম্যান্স ও রক্ষণাবেক্ষণযোগ্যতা উভয়ের ক্ষেত্রেই দারুণ সুফল পেয়েছি। এম্বেডিং বাস্তবায়নের বেশিরভাগ অংশ আমাদের LLM সার্ভিং স্ট্যাকের সাথে ভাগ করে নেওয়ার মাধ্যমে, এম্বেডিং মডেলগুলির রক্ষণাবেক্ষণের পেছনে উল্লেখযোগ্য ইঞ্জিনিয়ারিং কাজের প্রয়োজন ছাড়াই আমরা থ্রুপুটেও লাভবান হই।

মডেলগুলি বিকশিত হওয়ার সাথে সাথে, CPU-বাউন্ড এবং GPU-bound উভয় লেটেন্সি কমাতে আমরা আমাদের স্ট্যাকের প্রতিটি স্তর উন্নত করতে থাকব। Ivy এবং Tulip-এর মধ্যে আমাদের কাস্টম gRPC-ভিত্তিক প্রোটোকল আমাদের নেটওয়ার্ক লেটেন্সি কমাতে যোগাযোগ পরিবর্তন করতে দেয়, অন্যদিকে ROSE কাঠামোগত থ্রুপুট উন্নত করার একটি ভিত্তি প্রদান করে। উপরন্তু, ইকোসিস্টেম জুড়ে ফ্রি-থ্রেডেড Python-এর জন্য সমর্থন বৃদ্ধি পাওয়ার সাথে সাথে, আমরা ওভারহেড কমাতে Python-Rust ইন্টারঅপারেবিলিটি আরও উন্নত করতে সক্ষম হব।

তথ্যসূত্র

উদ্ধৃতি

BibTeX
@online{perplexity2026FastEmbeddingsOnGpus,
  author = {{Perplexity} and Nandor Licker and Sebastian Sepulveda and Phi Hoang and Jerry Ma},
  title = {{Fast embeddings on GPUs}},
  date = {2026-09-04},
  url = {https://www.perplexity.ai/hub/blog/fast-embeddings-on-gpus}
}