Batch process text embeddings
This commit is contained in:
1 parent
b69b983145
commit
126ac4d3b8
2 files changed
+42
-3
No files matched your search
@@ -209,3 +209,4 @@ class AdvancedPromptEmbeds:
|
|||||||
)
|
)
|
||||||
for i in range(num_parts):
|
for i in range(num_parts):
|
||||||
split_embeds[i]._store[key] = [values[i]]
|
split_embeds[i]._store[key] = [values[i]]
|
||||||
|
return split_embeds
|
||||||
@@ -34,10 +34,13 @@ import albumentations as A
|
|||||||
from toolkit.print import print_acc
|
from toolkit.print import print_acc
|
||||||
from toolkit.accelerator import get_accelerator
|
from toolkit.accelerator import get_accelerator
|
||||||
from toolkit.prompt_utils import PromptEmbeds
|
from toolkit.prompt_utils import PromptEmbeds
|
||||||
|
from toolkit.advanced_prompt_embeds import AdvancedPromptEmbeds
|
||||||
from torchvision.transforms import functional as TF
|
from torchvision.transforms import functional as TF
|
||||||
|
|
||||||
from toolkit.train_tools import get_torch_dtype
|
from toolkit.train_tools import get_torch_dtype
|
||||||
|
|
||||||
|
TEXT_EMBED_CACHE_BATCH = 16 # prompts per text-encoder forward when caching
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from toolkit.data_loader import AiToolkitDataset
|
from toolkit.data_loader import AiToolkitDataset
|
||||||
from toolkit.data_transfer_object.data_loader import FileItemDTO
|
from toolkit.data_transfer_object.data_loader import FileItemDTO
|
||||||
@@ -2489,6 +2492,38 @@ class TextEmbeddingCachingMixin:
|
|||||||
|
|
||||||
did_move = False
|
did_move = False
|
||||||
|
|
||||||
|
# plain-text prompts are encoded TEXT_EMBED_CACHE_BATCH per forward: a 9B text
|
||||||
|
# encoder at batch 1 is kernel-launch bound (~15% GPU busy)
|
||||||
|
pending = [] # (path, caption), plain text only
|
||||||
|
pending_paths = set()
|
||||||
|
batch_ok = [None] # None = untested; False = legacy PromptEmbeds, no per-item split
|
||||||
|
|
||||||
|
def flush_pending():
|
||||||
|
if not pending:
|
||||||
|
return
|
||||||
|
# similar lengths together: a batch is right-padded to its longest prompt
|
||||||
|
pending.sort(key=lambda t: len(t[1]))
|
||||||
|
size = 1 if batch_ok[0] is False else TEXT_EMBED_CACHE_BATCH
|
||||||
|
start = 0
|
||||||
|
while start < len(pending):
|
||||||
|
chunk = pending[start:start + size]
|
||||||
|
embeds = self.sd.encode_prompt([c for _, c in chunk])
|
||||||
|
if isinstance(embeds, AdvancedPromptEmbeds):
|
||||||
|
batch_ok[0] = True
|
||||||
|
parts = AdvancedPromptEmbeds.split_prompt_embeds(embeds, len(chunk))
|
||||||
|
elif len(chunk) == 1:
|
||||||
|
parts = [embeds]
|
||||||
|
else:
|
||||||
|
batch_ok[0] = False
|
||||||
|
size = 1
|
||||||
|
continue # redo this chunk one prompt at a time
|
||||||
|
for (path, _), part in zip(chunk, parts):
|
||||||
|
part.save(path)
|
||||||
|
del embeds, parts
|
||||||
|
start += len(chunk)
|
||||||
|
pending.clear()
|
||||||
|
pending_paths.clear()
|
||||||
|
|
||||||
# use tqdm to show progress
|
# use tqdm to show progress
|
||||||
i = 0
|
i = 0
|
||||||
for file_item in tqdm(self.file_list, desc='Caching text embeddings to disk'):
|
for file_item in tqdm(self.file_list, desc='Caching text embeddings to disk'):
|
||||||
@@ -2616,9 +2651,11 @@ class TextEmbeddingCachingMixin:
|
|||||||
file_item.tensor = None
|
file_item.tensor = None
|
||||||
else:
|
else:
|
||||||
for path, caption in encode_targets:
|
for path, caption in encode_targets:
|
||||||
prompt_embeds: PromptEmbeds = self.sd.encode_prompt(caption)
|
if path not in pending_paths:
|
||||||
prompt_embeds.save(path)
|
pending_paths.add(path)
|
||||||
del prompt_embeds
|
pending.append((path, caption))
|
||||||
|
if len(pending) >= 4 * TEXT_EMBED_CACHE_BATCH:
|
||||||
|
flush_pending()
|
||||||
if getattr(file_item, 'dopsd_self_ref', False):
|
if getattr(file_item, 'dopsd_self_ref', False):
|
||||||
# D-OPSD teacher embeds encode with the item's own media as the reference
|
# D-OPSD teacher embeds encode with the item's own media as the reference
|
||||||
control_video_paths = getattr(file_item, 'control_video_paths', None) or []
|
control_video_paths = getattr(file_item, 'control_video_paths', None) or []
|
||||||
@@ -2665,6 +2702,7 @@ class TextEmbeddingCachingMixin:
|
|||||||
del prompt_embeds
|
del prompt_embeds
|
||||||
file_item.is_text_embedding_cached = True
|
file_item.is_text_embedding_cached = True
|
||||||
i += 1
|
i += 1
|
||||||
|
flush_pending()
|
||||||
# restore device state
|
# restore device state
|
||||||
# if did_move:
|
# if did_move:
|
||||||
# self.sd.restore_device_state()
|
# self.sd.restore_device_state()
|
||||||
|
|||||||
Reference in new issue
Block a user