<commit_before>#include "graph/expression_graph.h"
#include <sstream>

#include "tensors/tensor_operators.h"

namespace marian {

ExpressionGraph::ExpressionGraph(bool inference, bool optimized)
    : inferenceOnly_(inference), optimized_(optimized), backend_(nullptr) {}

void ExpressionGraph::setDevice(DeviceId deviceId, Ptr<Device> device) {
  if(!backend_) {
    backend_ = BackendByDeviceId(deviceId, Config::seed);
    params_ = New<Parameters>();
    params_->init(backend_);
    if(device)
      tensors_ = New<Tensors>(backend_, device);
    else
      tensors_ = New<Tensors>(backend_);
  }
}

Expr ExpressionGraph::dropout(float prob, const Shape& shape) {
  return constant(shape, inits::dropout(prob));
}

void ExpressionGraph::checkNan(Tensor t, bool& isNan, bool& isInf, bool zero) {
  IsNan(t, allocator(), isNan, isInf, zero);
}

io::Item itemFromTensor(Tensor t, const std::string name, Ptr<Backend> backend) {
  io::Item item;
  item.name  = name;
  item.shape = t->shape();
  item.type  = t->type();

  size_t bytesWithoutPadding = t->shape().elements() * sizeOf(t->type());
  item.bytes.resize(bytesWithoutPadding);
  copy(backend,
        (char*)t->data(),
        (char*)t->data() + bytesWithoutPadding,
        item.bytes.data());
  return item;
}

void recChildren(Expr node, std::vector<io::Item>& items, Ptr<Backend> backend) {
  items.push_back(itemFromTensor(node->val(), "node" + std::to_string(node->getId()), backend));
  for(auto&& child : node->children())
    recChildren(child, items, backend);
}

void ExpressionGraph::forwardNext() {
  // @TODO: check if allocation works properly
  tensors_->clearShorttermMemory();

  while(!nodesForward_.empty()) {
    auto v = nodesForward_.front();
    v->allocate();
    v->init();
    v->forward();

    if(v->trainable() && throwNan_) {
      bool isNan = false, isInf = false;
      checkNan(v->val(), isNan, isInf);
      if(isNan || isInf) {
        LOG(critical, "Detected NaN ({}) or Inf ({}) in value (forward pass)", isNan, isInf);
        LOG(critical, "\tType: {}, Shape: {}, Name: {}, Id: {}, Hash: {}",
            v->type(), v->shape(), v->name(), v->getId(), v->hash());
        LOG(critical, "Value debug {}", v->val()->debug());

        LOG(critical, "Children: {}", v->children().size());
        for(auto&& child : v->children()) {
          LOG(critical, "\tType: {}, Shape: {}, Name: {}, Id: {}, Hash: {}",
            child->type(), child->shape(), child->name(), child->getId(), child->hash());
          LOG(critical, "Value debug {}", child->val()->debug());
        }

        std::vector<io::Item> ioItems;
        recChildren(v, ioItems, backend_);
        io::saveItems("dump-for-nans.npz", ioItems);

        ABORT("Aborting");
      }
    }

    if(v->marked_for_debug()) {
      LOG(info, "Debug: {} op={}", v->debug_message(), v->type());
      LOG(info, v->val()->debug());
    }

    if(inferenceOnly_)
      v->children().clear();
    nodesForward_.pop_front();
  }
}

void ExpressionGraph::backward(bool zero, float clipValue) {
  if(topNodes_.size() > 1) {
    LOG(critical, "There are more ({}) than one top most nodes for backward pass:", topNodes_.size());
    for(auto node : topNodes_) {
      LOG(critical,
          "\tType: {}, Shape: {}, Name: {}, Id: {}, Hash: {}",
          node->type(),<commit_msg>full graph below nide<commit_after>#include "graph/expression_graph.h"
#include <sstream>

#include "tensors/tensor_operators.h"

namespace marian {

ExpressionGraph::ExpressionGraph(bool inference, bool optimized)
    : inferenceOnly_(inference), optimized_(optimized), backend_(nullptr) {}

void ExpressionGraph::setDevice(DeviceId deviceId, Ptr<Device> device) {
  if(!backend_) {
    backend_ = BackendByDeviceId(deviceId, Config::seed);
    params_ = New<Parameters>();
    params_->init(backend_);
    if(device)
      tensors_ = New<Tensors>(backend_, device);
    else
      tensors_ = New<Tensors>(backend_);
  }
}

Expr ExpressionGraph::dropout(float prob, const Shape& shape) {
  return constant(shape, inits::dropout(prob));
}

void ExpressionGraph::checkNan(Tensor t, bool& isNan, bool& isInf, bool zero) {
  IsNan(t, allocator(), isNan, isInf, zero);
}

io::Item itemFromTensor(Tensor t, const std::string name, Ptr<Backend> backend) {
  io::Item item;
  item.name  = name;
  item.shape = t->shape();
  item.type  = t->type();

  size_t bytesWithoutPadding = t->shape().elements() * sizeOf(t->type());
  item.bytes.resize(bytesWithoutPadding);
  copy(backend,
        (char*)t->data(),
        (char*)t->data() + bytesWithoutPadding,
        item.bytes.data());
  return item;
}

void recChildren(Expr node, const std::string& parent, std::vector<io::Item>& items, Ptr<Backend> backend) {
  std::string name = node->type() + "_" + std::to_string(node->getId()) + "_p:" + parent;
  items.push_back(itemFromTensor(node->val(), name, backend));
  for(auto&& child : node->children())
    recChildren(child, std::to_string(node->getId()), items, backend);
}

void ExpressionGraph::forwardNext() {
  // @TODO: check if allocation works properly
  tensors_->clearShorttermMemory();

  while(!nodesForward_.empty()) {
    auto v = nodesForward_.front();
    v->allocate();
    v->init();
    v->forward();

    if(v->trainable() && throwNan_) {
      bool isNan = false, isInf = false;
      checkNan(v->val(), isNan, isInf);
      if(isNan || isInf) {
        LOG(critical, "Detected NaN ({}) or Inf ({}) in value (forward pass)", isNan, isInf);
        LOG(critical, "\tType: {}, Shape: {}, Name: {}, Id: {}, Hash: {}",
            v->type(), v->shape(), v->name(), v->getId(), v->hash());
        LOG(critical, "Value debug {}", v->val()->debug());

        LOG(critical, "Children: {}", v->children().size());
        for(auto&& child : v->children()) {
          LOG(critical, "\tType: {}, Shape: {}, Name: {}, Id: {}, Hash: {}",
            child->type(), child->shape(), child->name(), child->getId(), child->hash());
          LOG(critical, "Value debug {}", child->val()->debug());
        }

        std::vector<io::Item> ioItems;
        recChildren(v, "root", ioItems, backend_);
        io::saveItems("dump-for-nans.npz", ioItems);

        ABORT("Aborting");
      }
    }

    if(v->marked_for_debug()) {
      LOG(info, "Debug: {} op={}", v->debug_message(), v->type());
      LOG(info, v->val()->debug());
    }

    if(inferenceOnly_)
      v->children().clear();
    nodesForward_.pop_front();
  }
}

void ExpressionGraph::backward(bool zero, float clipValue) {
  if(topNodes_.size() > 1) {
    LOG(critical, "There are more ({}) than one top most nodes for backward pass:", topNodes_.size());
    for(auto node : topNodes_) {
      LOG(critical,
          "\tType: {}, Shape: {}, Name: {}, Id: {}, Hash: {}",
          node->type(),
{'fraction_non_alphanumeric': 0.19505008839127871, 'fraction_numerical': 0.0002946375957572186, 'mean_word_length': 3.5964793500338526, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 103, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4308328', 'n_tokens_mistral': 2197, 'n_tokens_neox': 2141, 'n_words': 464}