ამ პოსტში განვიხილავთ Flux.1-Dev მოდელს ტექსტიდან გამოსახულების გენერაციისთვის, მისი ფართო პოპულარობისა და გამოყენების გამო, და იმას, თუ როგორ შეიძლება მისი ინფერენციის სიჩქარის ოპტიმიზაცია LoRA-ების გამოყენებისას (~2.3x). მასთან ერთად გაწვრთნილია 30 ათასზე მეტი ადაპტერი (როგორც Hugging Face Hub პლატფორმაზეა აღნიშნული). აქედან გამომდინარე, მისი მნიშვნელობა საზოგადოებისთვის დიდია. აღსანიშნავია, რომ მიუხედავად იმისა, რომ ჩვენ ვაჩვენებთ სიჩქარის ზრდას Flux-ით, ჩვენი აზრით, ჩვენი "რეცეპტი" საკმარისად უნივერსალურია სხვა მოდელებზეც გამოსაყენებლად. თუ ვერ მოითმენთ, რომ კოდთან მუშაობა დაიწყოთ, გთხოვთ, იხილოთ თანდართული კოდის საცავი. LoRA-ების სერვირებისას გავრცელებულია მათი "ცხელი გაცვლა" (hotswap) – სხვადასხვა LoRA-ების ჩართვა და გამორთვა. LoRA ცვლის საბაზისო მოდელის არქიტექტურას. გარდა ამისა, LoRA-ები შეიძლება განსხვავდებოდეს ერთმანეთისგან – თითოეულ მათგანს შეიძლება ჰქონდეს ცვალებადი რანგები და სხვადასხვა ფენები, რომლებსაც ისინი ადაპტაციისთვის მიზნად ისახავენ. LoRA-ების ამ დინამიური თვისებების გასათვალისწინებლად, ჩვენ უნდა მივიღოთ აუცილებელი ზომები, რათა უზრუნველვყოთ გამოყენებული ოპტიმიზაციების სიმტკიცე. მაგალითად, ჩვენ შეგვიძლია გამოვიყენოთ `torch.compile` კონკრეტული LoRA-ით დატვირთულ მოდელზე, რათა მივიღოთ სიჩქარის ზრდა ინფერენციის შეყოვნებაში. თუმცა, როგორც კი LoRA-ს შევცვლით სხვა LoRA-თი (პოტენციურად განსხვავებული კონფიგურაციით), ჩვენ წავაწყდებით ხელახალი კომპილაციის პრობლემებს, რაც გამოიწვევს ინფერენციის შენელებას. ასევე შესაძლებელია LoRA პარამეტრების შერწყმა საბაზისო მოდელის პარამეტრებში, კომპილაციის გაშვება და LoRA პარამეტრების გაუქმება ახლის ჩატვირთვისას. თუმცა, ეს მიდგომა კვლავ წააწყდება ხელახალი კომპილაციის პრობლემას ინფერენციის ყოველი გაშვებისას, არქიტექტურული დონის პოტენციური ცვლილებების გამო. ჩვენი ოპტიმიზაციის რეცეპტი ითვალისწინებს ზემოთ აღნიშნულ სიტუაციებს, რათა იყოს მაქსიმალურად რეალისტური. ქვემოთ მოცემულია ჩვენი ოპტიმიზაციის რეცეპტის ძირითადი კომპონენტები: აღსანიშნავია, რომ ზემოთ აღნიშნულთა შორის, FP8 კვანტიზაცია არის ინფორმაციის დაკარგვით, მაგრამ ხშირად უზრუნველყოფს სიჩქარე-მეხსიერების ყველაზე შთამბეჭდავ კომპრომისს. მიუხედავად იმისა, რომ ჩვენ რეცეპტი ძირითადად NVIDIA GPU-ების გამოყენებით გამოვცადეთ, ის AMD GPU-ებზეც უნდა იმუშაოს. ჩვენს წინა ბლოგ-პოსტებში (პოსტი 1 და პოსტი 2) უკვე განვიხილეთ ჩვენი ოპტიმიზაციის რეცეპტის პირველი სამი კომპონენტის გამოყენების უპირატესობები. მათი ეტაპობრივად გამოყენება მხოლოდ რამდენიმე ხაზის კოდია: FA3 პროცესორი მოცემულია აქ. პრობლემები იჩენს თავს, როდესაც ვცდილობთ LoRA-ების ჩართვას და გამორთვას კომპილირებულ დიფუზიურ ტრანსფორმატორში (pipe.transformer) ხელახალი კომპილაციის გააქტიურების გარეშე. ჩვეულებრივ, LoRA-ების ჩატვირთვა და გადმოტვირთვა მოითხოვს ხელახალ კომპილაციას, რაც ანადგურებს კომპილაციით მიღებულ ნებისმიერ სიჩქარის უპირატესობას. საბედნიეროდ, არსებობს ხელახალი კომპილაციის საჭიროების თავიდან აცილების გზა. `hotswap=True` პარამეტრის გადაცემით, Diffusers მოდელის არქიტექტურას უცვლელს დატოვებს და მხოლოდ LoRA ადაპტერის წონებს გაცვლის, რაც ხელახალ კომპილაციას არ საჭიროებს. (შეგახსენებთ, `pipe`-ის პირველი გამოძახება ნელი იქნება, რადგან `torch.compile` არის "just-in-time" კომპილატორი. თუმცა, შემდგომი გამოძახებები მნიშვნელოვნად სწრაფი უნდა იყოს.) ეს ზოგადად იძლევა LoRA-ების გაცვლის საშუალებას ხელახალი კომპილაციის გარეშე, მაგრამ არსებობს შეზღუდვები: Diffusers-ში "ცხელი გაცვლის" და მისი შეზღუდვების შესახებ დამატებითი ინფორმაციისთვის იხილეთ დოკუმენტაციის hotswapping განყოფილება. ამ სამუშაო პროცესის სარგებელი აშკარა ხდება, როდესაც ვუყურებთ ინფერენციის შეყოვნებას კომპილაციის გარეშე, "ცხელი გაცვლის" გამოყენებით. ძირითადი დასკვნები: ჩვენს მიერ განხილული ოპტიმიზაციის რეცეპტი ვარაუდობს მძლავრი GPU-ს, როგორიცაა H100, ხელმისაწვდომობას. თუმცა, რა შეგვიძლია გავაკეთოთ, როდესაც შეზღუდული ვართ სამომხმარებლო GPU-ების, როგორიცაა RTX 4090, გამოყენებით? მოდით გავარკვიოთ. Flux.1-Dev-ს (ყოველგვარი LoRA-ს გარეშე), Bfloat16 მონაცემთა ტიპის გამოყენებით, დაახლოებით 33GB მეხსიერება სჭირდება გასაშვებად. LoRA მოდულის ზომის მიხედვით, და ყოველგვარი ოპტიმიზაციის გარეშე, მეხსიერების ეს ნაკვალევი შეიძლება კიდევ უფრო გაიზარდოს. ბევრ სამომხმარებლო GPU-ს, როგორიცაა RTX 4090, მხოლოდ 24GB აქვს. ამ სექციის დანარჩენ ნაწილში RTX 4090 მანქანას განვიხილავთ, როგორც ჩვენს საცდელ სტენდს. პირველ რიგში, Flux.1-Dev-ის სრული შესრულების უზრუნველსაყოფად, ჩვენ შეგვიძლია გამოვიყენოთ CPU-ზე გადმოტვირთვა (CPU offloading), რომლის დროსაც კომპონენტები, რომლებიც არ არის საჭირო მიმდინარე გამოთვლების შესასრულებლად, გადმოიტვირთება CPU-ზე მეტი ამაჩქარებლის მეხსიერების გასათავისუფლებლად. ამის გაკეთება საშუალებას გვაძლევს, მთელი კონვეიერი გავუშვათ ~22GB-ში 35.403 წამში RTX 4090-ზე. კომპილაციის ჩართვას შეუძლია შეყოვნების შემცირება 31.205 წამამდე (1.12x სიჩქარის ზრდა). კოდის თვალსაზრისით, ეს მხოლოდ რამდენიმე ხაზია: გაითვალისწინეთ, რომ აქ არ გამოგვიყენებია FP8 კვანტიზაცია, რადგან ის არ არის მხარდაჭერილი CPU-ზე გადმოტვირთვასთან და კომპილაციასთან ერთად (მხარდაჭერის პრობლემის თემა). ამიტომ, მხოლოდ FP8 კვანტიზაციის გამოყენება Flux Transformer-ზე არ არის საკმარისი მეხსიერების ამოწურვის პრობლემის შესამსუბუქებლად. ამ შემთხვევაში, გადავწყვიტეთ მისი ამოღება. მაშასადამე, FP8 კვანტიზაციის სქემის უპირატესობის გამოსაყენებლად, ჩვენ უნდა ვიპოვოთ გზა ამის გასაკეთებლად CPU-ზე გადმოტვირთვის გარეშე. Flux.1-Dev-ისთვის, თუ დამატებით გამოვიყენებთ კვანტიზაციას T5 ტექსტურ ენკოდერზე, ჩვენ შევძლებთ სრული კონვეიერის ჩატვირთვას და გაშვებას 24GB-ში. ქვემოთ მოცემულია შედეგების შედარება T5 ტექსტური ენკოდერის კვანტიზაციით და მის გარეშე (NF4 კვანტიზაცია bitsandbytes-დან). როგორც ზემოთ მოცემულ ფიგურაში შევამჩნევთ, T5 ტექსტური ენკოდერის კვანტიზაცია...