547 {
548 auto P = std::make_unique<Program>();
550 std::set<std::string>
names;
554 if (!
names.insert(
name).second) fail(31,
"the name '" +
name +
"' is declared twice");
555 };
556
557 if (!
node.contains(
"index") || !
node.at(
"index").is_object() ||
node.at(
"index").empty())
558 fail(31, "'index' is not a map of names to positive integers");
560 if (!
kv.value().is_number_integer() ||
kv.value().get<
int64_t>() <= 0)
561 fail(31,
"index '" +
kv.key() +
"' has size " +
kv.value().dump() +
", not a positive integer");
562 if (
kv.value().get<
int64_t>() > (1 << 24))
563 throw std::runtime_error(
"IR recurrence: index '" +
kv.key() +
"' of size " +
kv.value().dump() +
564 " is larger than ember's interpreter takes (2^24)");
566 p.index_of[
kv.key()] =
static_cast<int>(
p.index_names.size());
567 p.index_names.push_back(
kv.key());
568 p.index_sizes.push_back(
static_cast<int>(
kv.value().get<
int64_t>()));
569 }
570 p.iv.assign(
p.index_names.size(), 0);
571 auto add_tensor = [&](
const std::string&
name, TKind
kind,
const std::vector<int>& ids, std::vector<int>&
list) {
576 t.strides.assign(
t.sizes.size(), 1);
577 for (
size_t d =
t.sizes.size(); d-- > 1;)
t.strides[d - 1] =
t.strides[d] *
static_cast<size_t>(
t.sizes[d]);
579 t.numel *=
static_cast<size_t>(
s);
580 if (
t.numel > (
size_t(1) << 28))
581 throw std::runtime_error(
"IR recurrence: tensor '" +
name +
"' holds more than 2^28 elements, more than ember's interpreter takes");
582 }
583 t.pos =
static_cast<int>(
list.size());
584 const int id =
static_cast<int>(
p.tensors.size());
586 p.tensors.push_back(std::move(
t));
589 };
590
592 if (
node.contains(
"in"))
n_in =
node.at(
"in").is_array() ?
node.at(
"in").size() : 1;
595 fail(31,
"'inputs' declares " + std::to_string(
inputs.size()) +
" value(s) for the " + std::to_string(
n_in) +
596 " of 'in'");
597 for (
size_t v = 0;
v <
inputs.size(); ++
v) {
598 const std::string
where =
"inputs[" + std::to_string(
v) +
"]";
606 p.in_widths.push_back(
p.tensors[
id].numel);
607 }
608
609 if (
node.contains(
"weights") && !
node.at(
"weights").is_null()) {
610 if (!
node.at(
"weights").is_object()) fail(31,
"'weights' is not a map of declarations to tensor names");
612 if (!
kv.value().is_string() ||
kv.value().get<std::string>().empty())
613 fail(31,
"weight '" +
kv.key() +
"' does not name a tensor");
614 const std::string
where =
"weights '" +
kv.key() +
"'";
623 }
624 }
625
628 for (
size_t k = 0;
k <
src.size(); ++
k) {
630 a.where = std::string(
section) +
"[" + std::to_string(
k) +
"]";
634 if (
a.toks[
pos].kind != Tok::Eq)
635 fail(31,
a.where +
" does not parse: expected '=' at column " + std::to_string(
a.toks[
pos].column));
636 a.body_tok =
pos + 1;
639 dst.push_back(std::move(
a));
640 }
641 };
646 if (!
node.contains(
"readout") || !
node.at(
"readout").is_string()) fail(31,
"'readout' is not one assignment");
650 {
651 std::vector<Assign>
ro;
653 ro[0].where =
"readout";
654 p.readout = std::move(
ro[0]);
655 }
656 for (
size_t k = 0;
k <
p.update.size(); ++
k) {
659 }
660 for (
size_t k = 0;
k <
p.let.size(); ++
k) {
663 }
664 {
666 std::vector<int>
outs;
668 p.out =
p.readout.tensor;
669 p.out_width =
p.tensors[
p.out].numel;
670 }
671 p.init_of_state.assign(
p.states.size(), -1);
672 for (
size_t k = 0;
k <
p.init.size(); ++
k) {
674 if (
it ==
p.tensor_of.end() ||
p.tensors[
it->second].kind != TKind::State)
675 fail(33,
p.init[
k].where +
" assigns '" +
init_names[
k] +
"', which is not a state tensor (an update's)");
676 const Tensor&
st =
p.tensors[
it->second];
677 if (
p.init_of_state[
st.pos] >= 0) fail(33,
p.init[
k].where +
" assigns '" +
init_names[
k] +
"' a second time");
678 std::vector<int>
sizes;
680 if (
sizes !=
st.sizes) fail(33,
p.init[
k].where +
" assigns '" +
init_names[
k] +
"' with other sizes than its update");
681 p.init_of_state[
st.pos] =
static_cast<int>(
k);
682 p.init[
k].tensor =
it->second;
683 }
684
685 auto body = [&](Assign&
a,
const ReadRules&
r) {
a.body = BodyParser(
p,
a.toks,
a.body_tok,
a.where,
r,
a.lhs).parse(); };
687 for (
size_t k = 0;
k <
p.let.size(); ++
k)
body(
p.let[
k], ReadRules{true, true, true, static_cast<int>(k)});
689 body(
p.readout, ReadRules{true, true, true, static_cast<int>(p.let.size())});
690 for (
auto*
v : {&
p.init, &
p.let, &
p.update})
692 std::vector<Token>().swap(
p.readout.toks);
693
694 for (
size_t s = 0;
s <
p.states.size(); ++
s) {
695 const Tensor&
t =
p.tensors[
p.states[
s]];
700 st.init_body =
p.init_of_state[
s] >= 0;
701 p.state_info.push_back(std::move(
st));
702 p.new_state.emplace_back(
t.numel);
703 }
705 p.data.assign(
p.tensors.size(),
nullptr);
709}
void init(const std::vector< const float * > &weights, const std::vector< float * > &state) const
const float * p[kIrDepthSourcesMax]
enum ember_ir::expr::@33::Value::Shape shape
std::vector< Token > toks
std::vector< Value > items