აქ შემოდის PyTorch-ის წინასწარი (AoT) კომპილაცია. მოდელების დროულად კომპილაციის ნაცვლად (რაც არ არის ოპტიმალური ZeroGPU-ის ხანმოკლე პროცესებისთვის), AoT საშუალებას გაძლევთ ერთხელ მოახდინოთ ოპტიმიზაცია და მყისიერად გადატვირთოთ. შედეგი: უფრო სწრაფი დემოები და გამარტივებული გამოცდილება, 1.3-დან 1.8-ჯერ გაზრდილი სისწრაფით ისეთ მოდელებზე, როგორიცაა Flux, Wan და LTX 🔥. ამ პოსტში გაჩვენებთ, თუ როგორ უნდა დააყენოთ წინასწარი (AoT) კომპილაცია ZeroGPU Spaces-ში. განვიხილავთ მოწინავე ხრიკებს, როგორიცაა FP8 კვანტიზაცია და დინამიური ფორმები, და გაგიზიარებთ სამუშაო დემოებს, რომელთა გამოცდაც დაუყოვნებლივ შეგიძლიათ. თუ ვერ დაელოდებით, გეპატიჟებით, შეამოწმოთ ZeroGPU-ზე მომუშავე დემოები zerogpu-aoti ორგანიზაციაში. Pro მომხმარებლებს და Team / Enterprise ორგანიზაციის წევრებს შეუძლიათ ZeroGPU Spaces-ის შექმნა, ხოლო ნებისმიერ მსურველს შეუძლია მათი თავისუფლად გამოყენება (Pro, Team და Enterprise მომხმარებლები იღებენ 8-ჯერ მეტ ZeroGPU კვოტას). Spaces არის Hugging Face-ის მიერ შექმნილი პლატფორმა, რომელიც მანქანური სწავლების პრაქტიკოსებს საშუალებას აძლევს მარტივად გამოაქვეყნონ სადემონსტრაციო აპლიკაციები. ეს შესანიშნავად მუშაობს, მაგრამ შედეგად იტოვებს GPU-ს Space-ისთვის მთელი მისი სიცოცხლის მანძილზე – მაშინაც კი, როდესაც მას მომხმარებლის აქტივობა არ აქვს. როდესაც ხაზზე სრულდება .to('cuda') ბრძანება, PyTorch ახდენს NVIDIA დრაივერის ინიციალიზაციას, რომელიც აყენებს პროცესს CUDA-ზე სამუდამოდ. ეს არ არის რესურსების თვალსაზრისით ეფექტური, იმის გათვალისწინებით, რომ აპლიკაციის ტრაფიკი არ არის იდეალურად გლუვი, არამედ ძალზედ სპორადული და არათანაბარი. ZeroGPU იყენებს Just-in-Time მიდგომას GPU ინიციალიზაციისთვის. ნაცვლად იმისა, რომ ძირითადი პროცესი CUDA-ზე დააყენოს, ის ავტომატურად აფორკებს პროცესს, აყენებს მას CUDA-ზე, ასრულებს GPU ამოცანებს და ბოლოს კლავს ფორკს, როდესაც GPU უნდა გათავისუფლდეს. ეს ნიშნავს, რომ: Python-ის spaces პაკეტის წყალობით, ერთადერთი კოდის ცვლილება, რომელიც საჭიროა ამ ქცევის მისაღებად, შემდეგია: spaces-ის იმპორტირებით და @spaces.GPU დეკორატორის დამატებით, ჩვენ: ZeroGPU ამჟამად გამოყოფს H200-ის MIG სლაისს (3გ.71გბ პროფილი). დამატებითი MIG ზომები, მათ შორის სრული სლაისი (7გ.141გბ პროფილი) ხელმისაწვდომი იქნება 2025 წლის ბოლოს. თანამედროვე ML ფრეიმვორკებს, როგორიცაა PyTorch და JAX, აქვთ კომპილაციის კონცეფცია, რომელიც შეიძლება გამოყენებულ იქნას მოდელის შეყოვნების ან დასკვნის (inference) დროის ოპტიმიზაციისთვის. კულისებში, კომპილაცია იყენებს ოპტიმიზაციის რიგ ნაბიჯებს (ხშირად აპარატურაზე დამოკიდებულს), როგორიცაა ოპერატორების შერწყმა, მუდმივების დაკეცვა და ა.შ. PyTorch-ს (2.0 ვერსიიდან მოყოლებული) ამჟამად აქვს კომპილაციის ორი ძირითადი ინტერფეისი: torch.compile მშვენივრად მუშაობს სტანდარტულ გარემოში: ის აკომპილირებს თქვენს მოდელს პირველი გაშვებისას და ოპტიმიზებულ ვერსიას ხელახლა იყენებს შემდგომი გამოძახებებისთვის. თუმცა, ZeroGPU-ზე, იმის გათვალისწინებით, რომ პროცესი ახალია (თითქმის) ყოველი GPU ამოცანისთვის, ეს ნიშნავს, რომ torch.compile ვერ ახერხებს კომპილაციის ეფექტურად ხელახლა გამოყენებას და იძულებულია დაეყრდნოს თავის ფაილურ სისტემის ქეშს კომპილირებული მოდელების აღსადგენად. მოდელის სირთულიდან გამომდინარე, ამ პროცესს სჭირდება რამდენიმე ათეული წამიდან რამდენიმე წუთამდე, რაც ზედმეტად ბევრია Spaces-ში პრაქტიკული GPU ამოცანებისთვის. სწორედ აქ გამოირჩევა წინასწარი (AoT) კომპილაცია. AoT-ის საშუალებით, ჩვენ შეგვიძლია ერთხელ მოვახდინოთ კომპილირებული მოდელის ექსპორტი, შევინახოთ იგი და შემდეგ მყისიერად გადავტვირთოთ ნებისმიერ პროცესში, რაც ზუსტად ისაა, რაც გვჭირდება ZeroGPU-სთვის. ეს გვეხმარება შევამციროთ ფრეიმვორკის დანახარჯი და ასევე გამოვრიცხოთ ცივი სტარტის დრო, რომელიც ჩვეულებრივ წარმოიქმნება Just-in-Time კომპილაციისას. მაგრამ როგორ შევასრულოთ წინასწარი კომპილაცია ZeroGPU-ზე? მოდით, ჩავუღრმავდეთ. დავუბრუნდეთ ჩვენს ZeroGPU საბაზისო მაგალითს და განვიხილოთ, რა გვჭირდება AoT კომპილაციის ჩასართავად. ამ დემოს მიზნებისთვის, ჩვენ გამოვიყენებთ black-forest-labs/FLUX.1-dev მოდელს: ქვემოთ მოცემულ განხილვაში, ჩვენ ვაკომპილირებთ მხოლოდ pipe-ის ტრანსფორმატორის კომპონენტს, ვინაიდან ამ გენერაციულ მოდელებში ტრანსფორმატორი (ან უფრო ზოგადად, denoiser) არის ყველაზე გამოთვლითად მძიმე კომპონენტი. PyTorch-ით მოდელის წინასწარი კომპილაცია მრავალ ნაბიჯს მოიცავს: გაიხსენეთ, რომ მოდელს წინასწარ ვაკომპილირებთ. ამიტომ, მოდელისთვის გვჭირდება მაგალითის შეყვანების (inputs) გამოყვანა. გაითვალისწინეთ, რომ ეს არის იგივე სახის შეყვანები, რასაც რეალური გაშვების დროს ველოდებით. ამ შეყვანების დასაფიქსირებლად, ჩვენ გამოვიყენებთ spaces.aoti_capture დამხმარეს spaces პაკეტიდან: როგორც კონტექსტის მენეჯერი, aoti_capture აჩერებს ნებისმიერი გამოძახების (ჩვენს შემთხვევაში pipe.transformer-ის) შესრულებას, იჭერს შეყვანის არგუმენტებს, რომლებიც მას გადაეცემოდა, და ინახავს მათ მნიშვნელობებს call.args-სა და call.kwargs-ში. ახლა, როდესაც გვაქვს ჩვენი ტრანსფორმატორის კომპონენტისთვის მაგალითის args და kwargs, შეგვიძლია მისი ექსპორტირება PyTorch ExportedProgram-ში torch.export.export უტილიტის გამოყენებით: ექსპორტირებული PyTorch პროგრამა არის გამოთვლის გრაფიკი, რომელიც წარმოადგენს ტენზორულ გამოთვლებს ორიგინალური მოდელის პარამეტრების მნიშვნელობებთან ერთად. მოდელის ექსპორტირების შემდეგ, მისი კომპილაცია საკმაოდ მარტივია. PyTorch-ში ტრადიციული AoT კომპილაცია ხშირად მოითხოვს მოდელის დისკზე შენახვას, რათა მოგვიანებით მისი ხელახლა ჩატვირთვა მოხდეს. ჩვენს შემთხვევაში, ჩვენ გამოვიყენებთ დამხმარ ფუნქციას spaces პაკეტიდან: spaces.aoti_compile. ეს არის torch._inductor.aot_compile-ის პატარა შეფუთვა, რომელიც მართავს მოდელის შენახვას და საჭიროებისამებრ ზარმაცი დატვირთვას (lazy-loading). მისი გამოყენება განკუთვნილია ასე: ეს compiled_transformer ახლა AoT-ია.