.. _program_listing_file_src_graph_parameters.h: Program Listing for File parameters.h ===================================== |exhale_lsh| :ref:`Return to documentation for file ` (``src/graph/parameters.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #pragma once #include #include #include #include "common/definitions.h" #include "graph/chainable.h" #include "tensors/tensor_allocator.h" namespace marian { // @TODO: Currently an ExpressionGraph only supports one Parameters object and // the type of parameters has to be the inside on Parameters object. This limits // parameter types to a single chosen type, e.g. only fp32 or only fp16. This should // be extended to allow multiple sets of parameters. // The reason here is to be able to efficiently compute updates of whole parameter // sets of one type. class Parameters { protected: Type acceptedElementType_; // this parameter object only takes paramters of this type std::vector params_; std::map named_; Ptr vals_; Ptr grads_; size_t totalCapacity(Ptr alloc) { size_t sum = 0; for(auto p : params_) { sum += alloc->capacity(p->shape(), p->value_type()); } return sum; } public: Parameters(Type acceptedType) : acceptedElementType_(acceptedType) { LOG(debug, "Created parameter object of type {}", acceptedElementType_); } virtual ~Parameters() { LOG(debug, "Destroyed parameter object of type {}", acceptedElementType_); } auto begin() -> decltype(params_.begin()) { return params_.begin(); } auto end() -> decltype(params_.begin()) { return params_.end(); } auto getMap() -> decltype(named_)& { return named_; } Expr get(const std::string& name) { auto it = named_.find(name); if(it != named_.end()) { return it->second; } else { return Expr(); } } size_t size() { return params_.size(); } void add(Expr p, const std::string& name) { LOG(debug, "Adding parameter {} to parameter object of type {}", name, acceptedElementType_); ABORT_IF(named_.count(name), "Parameter '{}' already exists", name); ABORT_IF(p->value_type() != acceptedElementType_, "Requested parameter type ({}) is different from chosen parameter type ({})", p->value_type(), acceptedElementType_); params_.push_back(p); named_[name] = p; } virtual void init(Ptr backend) { vals_ = New(backend); grads_ = New(backend); } virtual void init(Ptr backend, Ptr device) { vals_ = New(backend, device); grads_ = New(backend, device); } virtual void allocateForward() { if(!params_.empty() && vals_->size() == 0) { vals_->reserveExact(totalCapacity(vals_)); // sort parameters by name before allocation to make sure the memory layout after allocation is always the same std::sort(params_.begin(), params_.end(), [](Expr n1, Expr n2){ return n1->name() < n2->name(); }); for(auto p : params_) { if(!p->val()) { vals_->allocate(p->val(), p->shape(), p->value_type()); } } } } virtual void allocateBackward() { if(!params_.empty() && grads_->size() == 0) { // sort parameters by name before allocation to make sure the memory layout after allocation is always the same std::sort(params_.begin(), params_.end(), [](Expr n1, Expr n2){ return n1->name() < n2->name(); }); grads_->reserveExact(totalCapacity(grads_)); for(auto p : params_) if(!p->grad()) grads_->allocate(p->grad(), p->shape(), p->value_type()); } } virtual void set_zero_adjoint() { grads()->set(0.f); } virtual Tensor vals() { return vals_->asTensor(acceptedElementType_); } virtual Tensor grads() { return grads_->asTensor(acceptedElementType_); } virtual void clear() { params_.clear(); named_.clear(); vals_->clear(); grads_->clear(); } }; class MappedParameters : public Parameters { private: Ptr backend_; public: MappedParameters(Type acceptedElementType) : Parameters(acceptedElementType) { LOG(debug, "Created mapped parameter object of type {}", acceptedElementType); } virtual void init(Ptr backend) override { backend_ = backend; } virtual void init(Ptr backend, Ptr) override { init(backend); } virtual void allocateForward() override { if(!params_.empty()) { for(auto p : params_) { if(!p->val()) { p->val() = TensorBase::New(nullptr, p->shape(), p->value_type(), backend_); } } } } virtual void allocateBackward() override { ABORT("Not implemented for memory-mapped parameters"); } virtual void set_zero_adjoint() override { ABORT("Not implemented for memory-mapped parameters"); } virtual Tensor vals() override { ABORT("Not implemented for memory-mapped parameters"); } virtual Tensor grads() override { ABORT("Not implemented for memory-mapped parameters"); } virtual void clear() override { params_.clear(); named_.clear(); } }; } // namespace marian