Skip to content

Commit 0a77c74

Browse files
committed
taehv: sequential encode
1 parent 5087690 commit 0a77c74

1 file changed

Lines changed: 125 additions & 32 deletions

File tree

src/model/vae/tae.hpp

Lines changed: 125 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,8 @@ class TinyDecoder : public UnaryBlock {
183183
};
184184

185185
class TPool : public UnaryBlock {
186-
int stride;
187-
188186
public:
187+
int stride;
189188
TPool(int channels, int stride)
190189
: stride(stride) {
191190
blocks["conv"] = std::shared_ptr<GGMLBlock>(new Conv2d(channels * stride, channels, {1, 1}, {1, 1}, {0, 0}, {1, 1}, false));
@@ -203,7 +202,7 @@ class TPool : public UnaryBlock {
203202
};
204203

205204
class TGrow : public UnaryBlock {
206-
public:
205+
public:
207206
int stride;
208207
TGrow(int channels, int stride)
209208
: stride(stride) {
@@ -356,6 +355,20 @@ ggml_tensor* unpatchify(ggml_context* ctx,
356355
return x;
357356
}
358357

358+
struct WorkItem {
359+
ggml_tensor* xt;
360+
int block_idx;
361+
};
362+
363+
struct SequentialDecoderState {
364+
std::map<int, ggml_tensor*> mem_single;
365+
};
366+
367+
struct SequentialEncoderState {
368+
std::map<int, ggml_tensor*> mem_single;
369+
std::map<int, std::vector<ggml_tensor*>> mem_pool;
370+
};
371+
359372
class TinyVideoEncoder : public UnaryBlock {
360373
int in_channels = 3;
361374
int hidden = 64;
@@ -364,6 +377,9 @@ class TinyVideoEncoder : public UnaryBlock {
364377
int num_layers = 3;
365378
int patch_size = 1;
366379

380+
int total_blocks = 0;
381+
int relu_idx = 0;
382+
367383
public:
368384
int t_downscale = 1;
369385
TinyVideoEncoder(int z_channels = 4, int patch_size = 1, std::vector<bool> time_downscale = {true, true, false})
@@ -376,7 +392,7 @@ class TinyVideoEncoder : public UnaryBlock {
376392
}
377393
int index = 0;
378394
blocks[std::to_string(index++)] = std::shared_ptr<GGMLBlock>(new Conv2d(in_channels * patch_size * patch_size, hidden, {3, 3}, {1, 1}, {1, 1}));
379-
index++; // nn.ReLU()
395+
relu_idx = index++; // nn.ReLU()
380396
for (int i = 0; i < num_layers; i++) {
381397
int stride = time_downscale[i] ? 2 : 1;
382398
blocks[std::to_string(index++)] = std::shared_ptr<GGMLBlock>(new TPool(hidden, stride));
@@ -385,7 +401,8 @@ class TinyVideoEncoder : public UnaryBlock {
385401
blocks[std::to_string(index++)] = std::shared_ptr<GGMLBlock>(new MemBlock(hidden, hidden));
386402
}
387403
}
388-
blocks[std::to_string(index)] = std::shared_ptr<GGMLBlock>(new Conv2d(hidden, z_channels, {3, 3}, {1, 1}, {1, 1}));
404+
blocks[std::to_string(index++)] = std::shared_ptr<GGMLBlock>(new Conv2d(hidden, z_channels, {3, 3}, {1, 1}, {1, 1}));
405+
total_blocks = index;
389406
}
390407

391408
ggml_tensor* forward(GGMLRunnerContext* ctx, ggml_tensor* z) override {
@@ -414,21 +431,96 @@ class TinyVideoEncoder : public UnaryBlock {
414431
}
415432
auto last_conv = std::dynamic_pointer_cast<Conv2d>(blocks[std::to_string(index)]);
416433
h = last_conv->forward(ctx, h);
434+
417435
return h;
418436
}
419-
};
420437

438+
ggml_tensor* forward_seq_single_step(GGMLRunnerContext* ctx,
439+
SequentialEncoderState& state,
440+
std::vector<WorkItem>& work_stack) {
441+
while (!work_stack.empty()) {
442+
WorkItem item = work_stack.back();
443+
work_stack.pop_back();
444+
445+
ggml_tensor* xt = item.xt;
446+
int i = item.block_idx;
421447

422-
struct WorkItem {
423-
ggml_tensor* xt;
424-
int block_idx;
425-
};
448+
if (i >= total_blocks) {
449+
if (patch_size > 1) {
450+
xt = unpatchify(ctx->ggml_ctx, xt, patch_size, 1);
451+
}
452+
return xt;
453+
}
426454

427-
// Stateful memory cache tracking MemBlock/WideMemBlock frames across steps
428-
struct TinyVideoDecoderState {
429-
std::map<int, ggml_tensor*> mem_single;
455+
if (i == relu_idx) {
456+
xt = ggml_relu_inplace(ctx->ggml_ctx, xt);
457+
work_stack.push_back({xt, i + 1});
458+
continue;
459+
}
460+
461+
std::string key = std::to_string(i);
462+
auto block = blocks[key];
463+
464+
if (auto mem_block = std::dynamic_pointer_cast<MemBlock>(block)) {
465+
ggml_tensor* prev_mem = state.mem_single[i];
466+
if (prev_mem == nullptr) {
467+
prev_mem = ggml_dup_tensor(ctx->ggml_ctx, xt);
468+
prev_mem = ggml_scale(ctx->ggml_ctx, prev_mem, 0.);
469+
}
470+
ggml_tensor* xt_next = mem_block->forward(ctx, xt, prev_mem);
471+
state.mem_single[i] = xt;
472+
473+
work_stack.push_back({xt_next, i + 1});
474+
} else if (auto pool = std::dynamic_pointer_cast<TPool>(block)) {
475+
state.mem_pool[i].push_back(xt);
476+
477+
if ((int)state.mem_pool[i].size() == pool->stride) {
478+
ggml_tensor* cat_input = ggml_ext_vec_concat(ctx->ggml_ctx, state.mem_pool[i], 3);
479+
ggml_tensor* xt_next = pool->forward(ctx, cat_input);
480+
481+
state.mem_pool[i].clear();
482+
work_stack.push_back({xt_next, i + 1});
483+
}
484+
} else if (auto unary_block = std::dynamic_pointer_cast<UnaryBlock>(block)) {
485+
ggml_tensor* xt_next = unary_block->forward(ctx, xt);
486+
work_stack.push_back({xt_next, i + 1});
487+
}
488+
}
489+
490+
return nullptr; // Work stack exhausted
491+
}
492+
493+
ggml_tensor* forward_seq(GGMLRunnerContext* ctx,
494+
ggml_tensor* z) {
495+
SequentialEncoderState state;
496+
std::vector<WorkItem> work_stack;
497+
498+
if (patch_size > 1) {
499+
z = patchify(ctx->ggml_ctx, z, patch_size, 1);
500+
}
501+
502+
const std::vector<ggml_tensor*>& latent_frames = ggml_ext_chunk(ctx->ggml_ctx, z, z->ne[3], 3);
503+
504+
for (auto it = latent_frames.rbegin(); it != latent_frames.rend(); ++it) {
505+
work_stack.push_back({*it, 0});
506+
}
507+
508+
std::vector<ggml_tensor*> output_frames;
509+
510+
while (!work_stack.empty()) {
511+
ggml_tensor* out_frame = forward_seq_single_step(ctx, state, work_stack);
512+
if (out_frame != nullptr) {
513+
output_frames.push_back(out_frame);
514+
}
515+
}
516+
517+
auto h = ggml_ext_vec_concat(ctx->ggml_ctx, output_frames, 3);
518+
return h;
519+
}
430520
};
431521

522+
523+
432524
class TinyVideoDecoder : public UnaryBlock {
433525
int z_channels = 4;
434526
int out_channels = 3;
@@ -439,10 +531,9 @@ class TinyVideoDecoder : public UnaryBlock {
439531
int t_upscale = 1;
440532
bool is_wide = false;
441533

442-
// Track total block index count and special unmapped activation indices
443-
int total_blocks = 0;
444-
int clamp_idx = 0;
445-
int relu1_idx = 0;
534+
int total_blocks = 0;
535+
int clamp_idx = 0;
536+
int relu1_idx = 0;
446537
int relu_final_idx = 0;
447538
std::set<int> upsample_indices;
448539

@@ -474,11 +565,11 @@ class TinyVideoDecoder : public UnaryBlock {
474565
blocks[std::to_string(index++)] = std::shared_ptr<GGMLBlock>(new MemBlock(channels[i], channels[i]));
475566
}
476567
}
477-
upsample_indices.insert(index++); // Nearest-neighbor spatial upsample slot
568+
upsample_indices.insert(index++); // Nearest-neighbor spatial upsample slot
478569
blocks[std::to_string(index++)] = std::shared_ptr<GGMLBlock>(new TGrow(channels[i], stride));
479570
blocks[std::to_string(index++)] = std::shared_ptr<GGMLBlock>(new Conv2d(channels[i], channels[i + 1], {3, 3}, {1, 1}, {1, 1}, {1, 1}, false));
480571
}
481-
relu_final_idx = index++; // nn.ReLU()
572+
relu_final_idx = index++; // nn.ReLU()
482573
blocks[std::to_string(index++)] = std::shared_ptr<GGMLBlock>(new Conv2d(channels[num_layers], out_channels * patch_size * patch_size, {3, 3}, {1, 1}, {1, 1}));
483574

484575
total_blocks = index;
@@ -530,7 +621,7 @@ class TinyVideoDecoder : public UnaryBlock {
530621
}
531622

532623
ggml_tensor* forward_seq_single_step(GGMLRunnerContext* ctx,
533-
TinyVideoDecoderState& state,
624+
SequentialDecoderState& state,
534625
std::vector<WorkItem>& work_stack) {
535626
while (!work_stack.empty()) {
536627
WorkItem item = work_stack.back();
@@ -615,12 +706,10 @@ class TinyVideoDecoder : public UnaryBlock {
615706

616707
return nullptr; // Work stack exhausted
617708
}
618-
619-
ggml_tensor* forward_seq(
620-
GGMLRunnerContext* ctx,
621-
ggml_tensor* x
622-
) {
623-
TinyVideoDecoderState state;
709+
710+
ggml_tensor* forward_seq(GGMLRunnerContext* ctx,
711+
ggml_tensor* x) {
712+
SequentialDecoderState state;
624713
std::vector<WorkItem> work_stack;
625714

626715
const std::vector<ggml_tensor*>& latent_frames = ggml_ext_chunk(ctx->ggml_ctx, x, x->ne[3], 3);
@@ -653,9 +742,9 @@ class TAEHV : public GGMLBlock {
653742
bool decode_only;
654743
SDVersion version;
655744
bool is_wide;
656-
657-
public:
658-
bool parallel = false;
745+
746+
public:
747+
bool parallel = false;
659748
int z_channels = 16;
660749
std::vector<bool> time_downscale = {true, true, false};
661750
std::vector<bool> time_upscale = {false, true, true};
@@ -710,7 +799,7 @@ class TAEHV : public GGMLBlock {
710799
x = ggml_concat(ctx->ggml_ctx, x, last_frame, 3);
711800
}
712801
}
713-
x = encoder->forward(ctx, x);
802+
x = parallel ? encoder->forward(ctx, x) : encoder->forward_seq(ctx, x);
714803
if (sd_version_is_wan(version) || sd_version_is_hunyuan_video(version) || sd_version_is_ltxav(version)) {
715804
// (W, H, C, T) -> (W, H, T, C)
716805
x = ggml_cont(ctx->ggml_ctx, ggml_permute(ctx->ggml_ctx, x, 0, 1, 3, 2));
@@ -878,12 +967,16 @@ struct TinyVideoAutoEncoder : public VAE {
878967

879968
ggml_cgraph* build_graph(const sd::Tensor<float>& z_tensor, bool decode_graph) {
880969
ggml_cgraph* gf = nullptr;
881-
ggml_tensor* z = make_input(z_tensor);
970+
ggml_tensor* z = make_input(z_tensor);
882971
if (decode_graph) {
883972
int64_t passes = taehv.parallel ? 1 : z->ne[3];
884973
gf = ggml_new_graph_custom(compute_ctx, (is_wide ? 4096 : 2048) * passes, false);
885974
} else {
886-
gf = ggml_new_graph(compute_ctx);
975+
int64_t frames = z->ne[2];
976+
int64_t factor = sd_version_is_minimax_h3(version) ? 20 : sd_version_is_ltxav(version) ? 8
977+
: 4;
978+
int64_t passes = taehv.parallel ? 1 : (frames + factor - 1) / factor;
979+
gf = ggml_new_graph_custom(compute_ctx, 2048 * passes, false);
887980
}
888981
auto runner_ctx = get_context();
889982
ggml_tensor* out = decode_graph ? taehv.decode(&runner_ctx, z) : taehv.encode(&runner_ctx, z);

0 commit comments

Comments
 (0)