def mem_eff_attention_gen_function_call(func_attrs, indent="  "):
    """the function for generating a function call for attention"""
    output_name = ""
    assert len(func_attrs["outputs"]) == 1
    assert len(func_attrs["inputs"]) in [3, 4, 5]

    output_name = func_attrs["outputs"][0]._attrs["name"]

    q_name = func_attrs["inputs"][0]._attrs["name"]
    k_name = func_attrs["inputs"][1]._attrs["name"]
    v_name = func_attrs["inputs"][2]._attrs["name"]

    variable_seq_length_kv = func_attrs["variable_seq_length_kv"]
    variable_seq_length_q = func_attrs["variable_seq_length_q"]

    lengths_name_kv = "nullptr"
    lengths_name_q = "nullptr"

    if variable_seq_length_kv:
        assert len(func_attrs["inputs"]) > 3
        lengths_name_kv = func_attrs["inputs"][3]._attrs["name"]
    if variable_seq_length_q:
        idx_len_q = 3 + variable_seq_length_kv
        assert len(func_attrs["inputs"]) > idx_len_q
        lengths_name_q = func_attrs["inputs"][idx_len_q]._attrs["name"]

    x = func_attrs["inputs"][0]
    xshape = x._attrs["shape"]
    batch_size = "&" + xshape[0]._attrs["name"]
    seq_len_q = "&" + xshape[2]._attrs["name"]

    num_heads = x._attrs["shape"][1]._attrs["values"][0]
    head_size = x._attrs["shape"][3]._attrs["values"][0]
    p_dropout = func_attrs["dropout"]
    is_causal = func_attrs["causal"]
    softmax_scale = head_size ** (-0.5)

    v = func_attrs["inputs"][2]
    vshape = v._attrs["shape"]
    seq_len_kv = "&" + vshape[2]._attrs["name"]

    head_size_v = v._attrs["shape"][3]._attrs["values"][0]

    backend_spec = CUDASpec()

    return FUNC_CALL_TEMPLATE.render(
        stream=backend_spec.stream,
        func_name=func_attrs["name"],
        output=output_name,
        query=q_name,
        key=k_name,
        value=v_name,
        batch_size=batch_size,
        seq_len_kv=seq_len_kv,
        seq_len_q=seq_len_q,
        num_heads=num_heads,
        head_size=head_size,
        head_size_v=head_size_v,
        p_dropout=p_dropout,
        softmax_scale=softmax_scale,
        is_causal="true" if is_causal else "false",
        fixed_seq_length_kv="false" if variable_seq_length_kv else "true",
        lengths_kv=f"static_cast<int32_t*>({lengths_name_kv})",
        fixed_seq_length_q="false" if variable_seq_length_q else "true",
        lengths_q=f"static_cast<int32_t*>({lengths_name_q})",
        indent=indent,
    )
the function for generating a function call for attention
python/aitemplate/backend/cuda/attention/mem_eff_attention.py