ეს ამოცანები ხშირად იყენებს ენკოდერულ მოდელებს, რომლებიც ბევრად მცირეა, ვიდრე თანამედროვე დიდი ენობრივი მოდელები (LLMs), თუმცა 1 მილიარდზე მეტი ინფერენციის მოთხოვნის მასშტაბით, ეს მაინც საკმაოდ რთული ამოცანაა. განმარტებისთვის, ეს ინგლისური ვიკიპედიის 144-ჯერადი მოცულობაა. მე არ მინახავს ბევრი ინფორმაცია იმის შესახებ, თუ როგორ უნდა მივუდგეთ ამ საკითხს ხარჯების გათვალისწინებით და მსურს ამ პრობლემის მოგვარება. ეს ბლოგი დეტალურად აღწერს, თუ როგორ უნდა გამოითვალოს ხარჯები და შეყოვნება მასშტაბური კლასიფიკაციისა და ემბედინგის ამოცანებისთვის. ჩვენ გავაანალიზებთ მოდელების სხვადასხვა არქიტექტურას, შევადარებთ ხარჯებს სხვადასხვა აპარატურულ არჩევანზე და მოგაწვდით მკაფიო ჩარჩოს თქვენი სისტემის ოპტიმიზაციისთვის. გარდა ამისა, თქვენ შეგეძლებათ გარკვეული ინტუიციის გამომუშავება, თუ არ გსურთ პროცესის თავად გავლა. შესაძლოა, რამდენიმე კითხვა გაგიჩნდეთ: აქ არის კოდი, რომელიც ამ ყველაფრის განხორციელებას უზრუნველყოფს: https://github.com/datavistics/encoder-analysis. შენიშვნა: დეტალური კოდის რეპროდუცირების ნაცვლად, წარმოდგენილია შედეგები. მოცემული ფასების გათვალისწინებით, შესაძლებელი გახდა ასეთი ხარჯის მიღება: ხარჯებისა და შეყოვნების შესაფასებლად, გვჭირდება 4 ძირითადი კომპონენტი: აპარატურული არჩევანისთვის გამოვიყენებ Inference Endpoints-ს, რადგან ის საშუალებას მაძლევს ავირჩიო აპარატურის ფართო სპექტრიდან. გაითვალისწინეთ, რომ შეგიძლიათ ის შეცვალოთ თქვენთვის სასურველი/განსახილველი გრაფიკული პროცესორებით (GPUs). განთავსების გამარტივებისთვის გამოვიყენებ ძალიან სასარგებლო Hugging Face Hub ბიბლიოთეკას, რომელიც მოდელების პროგრამულად მარტივად განთავსების საშუალებას იძლევა. ინფერენციის სერვერისთვის ასევე გამოვიყენებ Infinity-ს, რომელიც საოცარი ბიბლიოთეკაა ენკოდერული მოდელების (და ახლა უკვე მეტისაც!) სერვისისთვის. მე უკვე დავწერე TEI-ის შესახებ, რომელიც კიდევ ერთი შესანიშნავი ბიბლიოთეკაა. თქვენ აუცილებლად უნდა განიხილოთ TEI თქვენი კონკრეტული შემთხვევისთვის, თუმცა ეს ბლოგი ფოკუსირებულია მეთოდოლოგიაზე და არა ფრეიმვორკების შედარებაზე. Infinity-ს აქვს რამდენიმე ძირითადი უპირატესობა, როგორიცაა მულტიმოდალური ემბედინგების სერვისი, სხვადასხვა აპარატურაზე (AMD, Nvidia, CPU და Inferentia) მუშაობა და ნებისმიერი ახალი მოდელის გაშვება, რომელიც შეიცავს დისტანციურ კოდს და არ არის ინტეგრირებული Hugging Face-ის Transformer ბიბლიოთეკაში. ჩემთვის ყველაზე მნიშვნელოვანია ის, რომ მოდელების უმეტესობა თავსებადია ნაგულისხმევად. დატვირთვის ტესტირებისთვის გამოვიყენებ Grafana-ს k6-ს, რომელიც არის ღია კოდის დატვირთვის ტესტირების ინსტრუმენტი, დაწერილი Go-ზე JavaScript ინტერფეისით. ის ადვილად კონფიგურირებადია, აქვს მაღალი შესრულება და დაბალი დანახარჯი. მას აქვს მრავალი ჩაშენებული ეგზეკუტორი, რომლებიც ძალიან სასარგებლოა. ის ასევე წინასწარ ანაწილებს ვირტუალურ მომხმარებლებს (VUs), რაც ბევრად უფრო რეალისტურია, ვიდრე ტესტირების თავად აწყობა. მე განვიხილავ 3 გამოყენების შემთხვევას, რომელიც მრავალ საინტერესო საკითხს მოიცავს: ოპტიმიზაცია რთული საკითხია, რადგან ბევრი რამ არის გასათვალისწინებელი. ზოგადად, მსურს დატვირთვის ტესტირების მნიშვნელოვანი პარამეტრების გადამოწმება და იმის გარკვევა, თუ რა მუშაობს საუკეთესოდ ერთ გრაფიკულ პროცესორზე (GPU), რადგან ენკოდერული მოდელების უმეტესობა ეტევა ერთ GPU-ში. მას შემდეგ, რაც გვექნება ხარჯების საბაზისო მონაცემები ერთი GPU-სთვის, GPU-ების რაოდენობა და გამტარუნარიანობა შეიძლება ჰორიზონტალურად გაიზარდოს რეპლიკა GPU-ების რაოდენობის გაზრდით. თითოეული გამოყენების შემთხვევისთვის, ეს არის მაღალი დონის ნაკადი, რომელსაც გამოვიყენებ: რადგან კოდი ხელმისაწვდომია, თავისუფლად შეგიძლიათ შეცვალოთ ნებისმიერი ნაწილი თქვენი საჭიროების მიხედვით. ვირტუალური მომხმარებლები (VUs) და ბატჩის ზომა (Batch Size) მნიშვნელოვანია, რადგან ისინი გავლენას ახდენენ იმაზე, თუ რამდენად კარგად ვიყენებთ GPU-ში არსებულ ყველა გამოთვლით რესურსს. საკმარისად დიდი ბატჩის ზომა უზრუნველყოფს Streaming Multiprocessors-ისა და ვიდეო მეხსიერების (VRAM) სრულ გამოყენებას. არის სცენარები, როდესაც VRAM რჩება გამოუყენებელი, მაგრამ არსებობს გამტარუნარიანობის ხარჯი, რომელიც ხელს უშლის გამტარუნარიანობის ზრდას. ამიტომ, ექსპერიმენტები შეიძლება დაგვეხმაროს. VUs საშუალებას გვაძლევს დავრწმუნდეთ, რომ სრულად ვიყენებთ ჩვენს ხელთ არსებულ ბატჩის ზომას. ეს არის ძირითადი პარამეტრები, რომლებსაც შევამოწმებ: თქვენი მოდელის მიხედვით, შესაძლოა მოგინდეთ შემდეგი საკითხების განხილვა: k6 შესანიშნავია, რადგან ის საშუალებას გაძლევთ წინასწარ გამოყოთ VUs და თავიდან აიცილოთ ზოგიერთი ფარული შეცდომა. ის საკმაოდ მოქნილია მოთხოვნების გაგზავნის თვალსაზრისით. მე გადავწყვიტე მისი კონკრეტული გზით გამოყენება. როდესაც k6 ექსპერიმენტს ვატარებ, ძირითადად მინდა ვიცოდე მოთხოვნების გამტარუნარიანობა და საშუალო შეყოვნება, ასევე ჩავატარო რამდენიმე საბაზისო შემოწმება დატვირთვის ტესტირების პარამეტრებისთვის, რომლებიც ავირჩიე. ასევე მსურს ფართო სპექტრის ექსპერიმენტების ჩატარება. მე ვიყენებ shared-iterations executor-ს (დოკუმენტაცია), რაც ნიშნავს, რომ k6 იტერაციებს ანაწილებს VUs რაოდენობას შორის. ტესტი სრულდება, როდესაც k6 ასრულებს ყველა იტერაციას. ეს საშუალებას მაძლევს მქონდეს გონივრული დროის ლიმიტი, მაგრამ ასევე გავაგზავნო საკმარისი რაოდენობის მოთხოვნები, რათა მქონდეს ადეკვატური ნდობა, რომ შემიძლია განვასხვავო დატვირთვის ტესტირების პარამეტრების არჩევანი ჩემს კვლევაში. სხვა ეგზეკუტორებისგან განსხვავებით, ეს საშუალებას მაძლევს დარწმუნებული ვიყო, რომ კლიენტს სიმულირებას ვუკეთებ, როგორც მაქსიმალურად დატვირთულს თითოეული VU-ისთვის, რამაც უნდა მიჩვენოს ყველაზე იაფი ვარიანტი. მე ვიყენებ 10,000 მოთხოვნას† და მაქსიმალური ექსპერიმენტის დრო 1 წუთია. ასე რომ, თუ 10,000 მოთხოვნა არ დასრულდება 1 წუთში, მაშინ ეს ექსპერიმენტი სრულდება. † ვიზუალური ემბედინგებისთვის (Vision Embeddings) ნაკლებ მაქსიმალურ მოთხოვნას ვიყენებ, იმის გათვალისწინებით, რომ გამტარუნარიანობა ბევრად დაბალია და სურათები მძიმეა. †† P95 ნიშნავს, რომ მოთხოვნების 95% სრულდება ამ დროში. ის წარმოადგენს ყველაზე ცუდ შეყოვნებას მომხმარებლების უმეტესობისთვის. სამივე ნოუთბუქი, რომელიც ოპტიმიზაციის სამუშაო პროცესს აერთიანებს, შეგიძლიათ იპოვოთ აქ: მთავარი მიზანი იყო ჩემი ექსპერიმენტების განსაზღვრა, გაშვება.