Spaces:
Running on Zero
Running on Zero
Download serve/cache.py from hugging-apps/maya2-native: direct link, hf CLI and curl.
- Browser
- Download file 2.61 kB
-
https://huggingface.co/spaces/hugging-apps/maya2-native/resolve/main/serve/cache.py
- Command line
-
hf download hf://spaces/hugging-apps/maya2-native/serve/cache.py
-
curl -L -o cache.py https://huggingface.co/spaces/hugging-apps/maya2-native/resolve/main/serve/cache.py
2.61 kB
| """Reference ragged-cache batching; positions remain local to each seat.""" | |
| import torch | |
| from transformers import DynamicCache | |
| from transformers.cache_utils import DynamicLayer | |
| def cache_from_owned_tensors(layers): | |
| """Install freshly owned tensors without concatenating them to empty caches. | |
| DynamicCache(ddp_cache_data=...) calls update(), which copies every tensor | |
| once more. These inputs are already owned by this cache, so initialization | |
| can install them directly using the pinned DynamicLayer representation. | |
| """ | |
| cache=DynamicCache() | |
| for keys,values in layers: | |
| layer=DynamicLayer() | |
| layer.keys,layer.values=keys,values | |
| layer.dtype,layer.device=keys.dtype,keys.device | |
| layer.is_initialized=True | |
| cache.layers.append(layer) | |
| return cache | |
| def pack_caches(caches, new_tokens, device): | |
| lengths=[c.layers[0].keys.shape[-2] if c is not None else 0 for c in caches] | |
| maximum=max(lengths) | |
| if maximum==0: | |
| return None,None,lengths | |
| exemplar=next(c for c in caches if c is not None) | |
| layers=[] | |
| for li in range(len(exemplar.layers)): | |
| kv=[] | |
| for name in ('keys','values'): | |
| sample=getattr(exemplar.layers[li],name) | |
| stacked=sample.new_zeros(len(caches),sample.shape[1],maximum,sample.shape[-1]) | |
| for i,(c,length) in enumerate(zip(caches,lengths)): | |
| if length: | |
| stacked[i:i+1,:,-length:]=getattr(c.layers[li],name) | |
| kv.append(stacked) | |
| layers.append(tuple(kv)) | |
| mask=torch.arange(maximum+new_tokens,device=device)[None]>=torch.tensor( | |
| [maximum-l for l in lengths],device=device)[:,None] | |
| return cache_from_owned_tensors(layers),mask,lengths | |
| def split_cache(cache,lengths,keep=None,*,copy=True): | |
| """Split cache rows, optionally borrowing immutable views for experiments. | |
| The default gives independent mutable storage. copy=False permits only | |
| DynamicLayer append/crop operations, which replace tensors rather than | |
| writing existing storage. A borrowed row retains the whole packed batch | |
| until all views die; measure memory before using it in a serving path. | |
| """ | |
| def take(tensor,i,length): | |
| view=tensor[i:i+1,:,-length:] | |
| return view.clone(memory_format=torch.contiguous_format) if copy else view | |
| result=[] | |
| for i,length in enumerate(lengths): | |
| length=min(length,keep) if keep is not None else length | |
| result.append(cache_from_owned_tensors([ | |
| (take(l.keys,i,length),take(l.values,i,length)) for l in cache.layers])) | |
| return result | |