Configure video pipeline and text encoder GPUs with memory guidance
This commit is contained in:
@@ -11,18 +11,30 @@ import threading
|
||||
import time
|
||||
import uuid
|
||||
from image_test import probe,cgroup_headroom,GIB
|
||||
from profiles import video_recipe
|
||||
from profiles import video_recipe,video_parameters
|
||||
|
||||
def video_devices(profile,gpus):
|
||||
if not gpus:raise ValueError('Keine Video-GPU verfügbar.')
|
||||
params=video_parameters(profile.get('parameters',{}))
|
||||
def selected(value):
|
||||
found=next((g for g in gpus if g['uuid']==value),None)
|
||||
if not found:raise ValueError('Im Videoprofil ausgewählte GPU nicht verfügbar: '+value)
|
||||
return found
|
||||
gpu=(next((g for g in gpus if '5080' in g.get('name','')),None) or max(gpus,key=lambda g:g['total_mib'])) if params['video_device']=='auto' else selected(params['video_device'])
|
||||
encoder=gpu if params['text_encoder_device']=='same' else selected(params['text_encoder_device'])
|
||||
devices=[gpu] if encoder['uuid']==gpu['uuid'] else [gpu,encoder]
|
||||
return gpu,encoder,devices
|
||||
|
||||
class Video:
|
||||
def __init__(self,root,profiles,runtime,scheduler,stop_owned):
|
||||
self.root=Path(root);self.profiles=profiles;self.runtime=runtime;self.scheduler=scheduler;self.stop_owned=stop_owned
|
||||
self.lock=threading.RLock();self.mode='llm';self.state='idle';self.error=None;self.process=None;self.profile=None;self.job=None;self.thread=None;self.gpu=None
|
||||
self.lock=threading.RLock();self.mode='llm';self.state='idle';self.error=None;self.process=None;self.profile=None;self.job=None;self.thread=None;self.gpu=None;self.device_names={}
|
||||
self.switch_phase=None;self.switch_started_at=None;self.target_mode=None;self.closing=False;self.selected=None
|
||||
if (self.root/'selection.json').exists():self.selected=json.loads((self.root/'selection.json').read_text()).get('profile_id')
|
||||
def status(self):
|
||||
with self.lock:
|
||||
if self.process and self.process.poll() is not None and self.state=='ready':self.state='failed';self.error='Video-Worker beendet; RAM-OOM oder Laufzeitfehler möglich.'
|
||||
return dict(target_mode=self.target_mode,switch_phase=self.switch_phase,switch_started_at=self.switch_started_at,mode=self.mode,state=self.state,error=self.error,profile_name=self.profile['name'] if self.profile else None,profile_id=self.selected,loaded_profile_id=self.profile['id'] if self.profile else None,gpu=self.gpu,job=dict(self.job) if self.job else None,runtime=self.runtime.status(),memory_policy='Disk-Streaming auf RTX 5080; beide GPUs exklusiv reserviert. Gewichte werden bedarfsgerecht geladen.')
|
||||
return dict(devices=dict(self.device_names),target_mode=self.target_mode,switch_phase=self.switch_phase,switch_started_at=self.switch_started_at,mode=self.mode,state=self.state,error=self.error,profile_name=self.profile['name'] if self.profile else None,profile_id=self.selected,loaded_profile_id=self.profile['id'] if self.profile else None,gpu=self.gpu,job=dict(self.job) if self.job else None,runtime=self.runtime.status(),memory_policy='Disk-Streaming auf den im Profil gewählten GPUs; GPUs exklusiv reserviert. Gewichte werden bedarfsgerecht geladen.')
|
||||
def blockers(self,p):
|
||||
if not video_recipe(p.get('model') or {}):return ['Für diese Videovariante ist kein Worker angebunden.']
|
||||
errors=[]
|
||||
@@ -119,8 +131,7 @@ class Video:
|
||||
def load(self,profile):
|
||||
gpus=probe()
|
||||
if not gpus or any(g['processes'] for g in gpus):raise ValueError('GPU durch fremden Dienst belegt. Fremden Dienst zuerst freigeben; Deck beendet ihn nicht.')
|
||||
gpu=next((g for g in gpus if '5080' in g.get('name','')),None)
|
||||
if gpu is None:gpu=max(gpus,key=lambda g:g['total_mib'])
|
||||
gpu,encoder,devices=video_devices(profile,gpus)
|
||||
if gpu['free_mib']<12000:raise ValueError('Mindestens 12 GiB freier GPU-Speicher für den Video-Test erforderlich.')
|
||||
available=next((int(line.split()[1])*1024 for line in Path('/proc/meminfo').read_text().splitlines() if line.startswith('MemAvailable:')),0)
|
||||
if available<10*GIB:raise ValueError('Mindestens 10 GiB verfügbarer Host-RAM erforderlich.')
|
||||
@@ -129,12 +140,14 @@ class Video:
|
||||
def path(entry):return str((self.profiles.catalog.root/entry['id']/('model'+Path(entry['file']).suffix)).resolve())
|
||||
components={role:self.profiles._component(profile['model'],role,profile['components'][role]) for role in video_recipe(profile['model'])}
|
||||
config=dict(paths=dict(transformer_path=path(profile['model']),text_encoder_path=path(components['text_encoder']),video_vae_path=path(components['video_vae']),audio_vae_path=path(components['audio_vae'])),spatial_upsampler=path(components['spatial_upsampler']))
|
||||
config['text_encoder_device']='cuda:0' if len(devices)==1 else 'cuda:1'
|
||||
config['device_names']={'video':gpu['name'],'text_encoder':encoder['name']}
|
||||
env={k:v for k,v in os.environ.items() if not k.startswith(('HF_','DECK_','LLAMA_'))}
|
||||
env.update(CUDA_VISIBLE_DEVICES=gpu['uuid'],HF_HUB_OFFLINE='1',TRANSFORMERS_OFFLINE='1',OMP_NUM_THREADS='2',TOKENIZERS_PARALLELISM='false')
|
||||
env.update(CUDA_VISIBLE_DEVICES=','.join(g['uuid'] for g in devices),HF_HUB_OFFLINE='1',TRANSFORMERS_OFFLINE='1',OMP_NUM_THREADS='2',TOKENIZERS_PARALLELISM='false')
|
||||
self.root.mkdir(parents=True,exist_ok=True,mode=0o700);env.update(HOME=str(self.root),TMPDIR=str(self.root))
|
||||
python,_=self.runtime.paths()
|
||||
p=subprocess.Popen([str(python),str(Path(__file__).with_name('video_worker.py'))],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.DEVNULL,bufsize=0,start_new_session=True,env=env)
|
||||
with self.lock:self.process=p;self.gpu=gpu['uuid']
|
||||
with self.lock:self.process=p;self.gpu=gpu['uuid'];self.device_names=dict(config['device_names'])
|
||||
if self.closing:self.stop_process();raise ValueError('Deck wird beendet.')
|
||||
with self.lock:self.switch_phase='Video-Worker laden und Komponenten prüfen'
|
||||
p.stdin.write((json.dumps(config)+'\n').encode());p.stdin.flush();result=self.read(p,180)
|
||||
|
||||
Reference in New Issue
Block a user