Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 42 additions & 44 deletions megatron/core/ssm/gated_delta_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,18 @@
from megatron.core.utils import deprecate_inference_params, nvtx_range_pop, nvtx_range_push

try:
from fla.modules.convolution import causal_conv1d
from fla.modules.l2norm import l2norm
from fla.ops.gated_delta_rule import chunk_gated_delta_rule

HAVE_FLA = True
except ImportError:
causal_conv1d = None
l2norm = None
chunk_gated_delta_rule = None

HAVE_FLA = False

try:
from causal_conv1d import causal_conv1d_fn
except ImportError:
causal_conv1d_fn = None


logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -204,6 +202,11 @@ def __init__(
)
setattr(self.A_log, "tensor_model_parallel", True)

if self.config.deterministic_mode:
self.gated_delta_rule = torch_chunk_gated_delta_rule
else:
self.gated_delta_rule = chunk_gated_delta_rule

# Output layernorm before projection
self.out_norm = build_module(
submodules.out_norm,
Expand Down Expand Up @@ -337,8 +340,8 @@ def forward(
alpha = alpha.reshape(batch, seq_len, -1)

# Convolution on qkv
qkv = qkv.transpose(1, 2).contiguous() # b, s, d -> b, d, s
nvtx_range_push(suffix="conv1d")
seq_len = qkv.shape[1]
qkv_channels_split_sections = [
self.qk_dim_local_tp,
self.qk_dim_local_tp,
Expand All @@ -360,9 +363,10 @@ def forward(
if self.conv_bias
else None
)
if (causal_conv1d_fn is None) or self.config.deterministic_mode:
if self.config.deterministic_mode:
qkv = qkv.transpose(1, 2).contiguous() # b, s, d -> b, d, s
conv_out = F.conv1d(
input=qkv,
input=qkv, # Torch-native only accept [b, d, s] format input
weight=conv1d_weight,
bias=conv1d_bias,
stride=self.conv1d.stride,
Expand All @@ -371,33 +375,39 @@ def forward(
groups=self.conv_dim_local_tp // self.cp_size,
)
qkv = self.act_fn(conv_out[..., :seq_len])
qkv = qkv.transpose(1, 2) # b, d, s -> b, s, d
else:
assert self.activation in ["silu", "swish"]
qkv = causal_conv1d_fn(
x=qkv,
qkv, _ = causal_conv1d(
x=qkv, # FLA conv1d accepts [b, s, d] format input
weight=conv1d_weight.squeeze(1), # d, 1, w -> d, w
bias=conv1d_bias,
activation=self.activation,
initial_state=None,
output_final_state=False,
)
nvtx_range_pop(suffix="conv1d")
# Split qkv into query, key, and value
qkv = qkv.transpose(1, 2) # b, d, s -> b, s, d
query, key, value = torch.split(

# Split qkv into query_key, and value
query_key, value = torch.split(
qkv,
[
self.qk_dim_local_tp // self.cp_size,
self.qk_dim_local_tp // self.cp_size,
self.v_dim_local_tp // self.cp_size,
],
[2 * self.qk_dim_local_tp // self.cp_size, self.v_dim_local_tp // self.cp_size],
dim=-1,
)
query = query.reshape(batch, seq_len, -1, self.key_head_dim)
key = key.reshape(batch, seq_len, -1, self.key_head_dim)
query_key = query_key.reshape(batch, seq_len, -1, self.key_head_dim)
value = value.reshape(batch, seq_len, -1, self.value_head_dim)
# Apply L2 norm to query and key
if self.use_qk_l2norm:
query = l2norm(query.contiguous())
key = l2norm(key.contiguous())
query_key = l2norm(query_key.contiguous())
# Split query and key.
query, key = torch.split(
query_key,
[
self.qk_dim_local_tp // self.key_head_dim // self.cp_size,
self.qk_dim_local_tp // self.key_head_dim // self.cp_size,
],
dim=2,
)
if self.num_value_heads // self.num_key_heads > 1:
query = query.repeat_interleave(self.num_value_heads // self.num_key_heads, dim=2)
key = key.repeat_interleave(self.num_value_heads // self.num_key_heads, dim=2)
Expand All @@ -421,28 +431,16 @@ def forward(
nvtx_range_pop(suffix="g_and_beta")

nvtx_range_push(suffix="gated_delta_rule")
if self.config.deterministic_mode:
core_attn_out, last_recurrent_state = torch_chunk_gated_delta_rule(
query,
key,
value,
g=g,
beta=beta,
initial_state=None,
output_final_state=False,
use_qk_l2norm_in_kernel=False,
)
else:
core_attn_out, last_recurrent_state = chunk_gated_delta_rule(
query,
key,
value,
g=g,
beta=beta,
initial_state=None,
output_final_state=False,
use_qk_l2norm_in_kernel=False,
)
core_attn_out, last_recurrent_state = self.gated_delta_rule(
query,
key,
value,
g=g,
beta=beta,
initial_state=None,
output_final_state=False,
use_qk_l2norm_in_kernel=False,
)
nvtx_range_pop(suffix="gated_delta_rule")

# RMSNorm
Expand Down
Loading