Skip to content
Open
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ enable_testing()

option(GLOW_WITH_CPU "Build the LLVM-based JIT CPU backend" ON)
option(GLOW_WITH_OPENCL "Build the OpenCL backend" ON)
option(GLOW_WITH_SOPHON "Build the Sophon backend" OFF)
option(GLOW_BUILD_EXAMPLES "Build the examples" ON)
option(GLOW_BUILD_TESTS "Build the tests" ON)
option(GLOW_WITH_BUNDLES "Build bundles" OFF)
Expand Down
8 changes: 8 additions & 0 deletions lib/Backends/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)

add_library(Backends Backends.cpp)

add_library(BackendUtils BackendUtils.cpp)
Expand All @@ -20,6 +22,12 @@ if(GLOW_WITH_CPU)
LIST(APPEND linked_backends CPUBackend)
endif()


if(GLOW_WITH_SOPHON)
add_subdirectory(Sophon)
LIST(APPEND linked_backends Sophon)
endif()

target_link_libraries(Backends
PRIVATE
BackendUtils
Expand Down
60 changes: 60 additions & 0 deletions lib/Backends/Sophon/AllocationsInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GLOW_BACKENDS_CPU_ALLOCATIONSINFO_H
#define GLOW_BACKENDS_CPU_ALLOCATIONSINFO_H

#include "llvm/ADT/DenseMap.h"

namespace glow {
class Value;
class IRFunction;
class Context;

/// Information about allocations for activations, constant weight variables
/// and mutable weight variables.
class AllocationsInfo {

public:
virtual ~AllocationsInfo() = default;
/// Assign offsets to all of the variables in the module \p M and to the
/// placeholders. \p ctx is the context that maps the graph to the concrete
/// execution environment for a specific function.
/// If the \p absoluteAddr is true, simply reuse the addresses already used
/// by the payloads of tensors corresponding to those WeightVars as offsets.
/// This is useful in a JIT setup. If \p absoluteAddr is false, then all the
/// WeightVars will get new offsets assigned.
virtual void allocateWeightVars(const IRFunction *F) = 0;
/// Assign offsets to all activations.
/// No actual memory allocation is performed. All the allocations should be
/// performed by the client based on the information provided by the
/// AllocationsInfo.
virtual void allocateActivations(const IRFunction *F) = 0;
/// Assign offsets to all tensorviews.
/// No memory allocation is performed. Sets up all offsets into already
/// defined offsets for WeightVars and AllocActivations. Assumes the weight
/// vars and alloc activations have already been added to allocatedAddressed_.
virtual void allocateTensorViews(const IRFunction *F) = 0;
/// Number all allocations and weight variables by assigning them unique
/// numbers.
virtual void numberValues(const IRFunction *F) = 0;

virtual llvm::DenseMap<const Value *, uint64_t> &getAllocatedAddress() = 0;
virtual void setActivationsMemSize(size_t v) = 0;
virtual size_t getActivationsMemSize() = 0;
};

} // namespace glow
#endif // GLOW_BACKENDS_CPU_ALLOCATIONSINFO_H
142 changes: 142 additions & 0 deletions lib/Backends/Sophon/BM188x/BM1880AllocationsInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#define DEBUG_TYPE "bm1880-alloc"

#include "BM1880AllocationsInfo.h"
#include "glow/CodeGen/MemoryAllocator.h"
#include "glow/Graph/Context.h"
#include "glow/Graph/Graph.h"
#include "glow/Graph/Nodes.h"
#include "glow/IR/IRUtils.h"
#include "glow/IR/Instrs.h"
#include "glow/Support/Debug.h"

#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

using namespace glow;
using llvm::cast;
using llvm::dyn_cast;
using llvm::isa;

BM1880AllocationsInfo::BM1880AllocationsInfo() : TTI_(nullptr) {}

BM1880AllocationsInfo::BM1880AllocationsInfo(
const sophon::SophonTargetTransformInfo *TTI)
: TTI_(TTI) {}

void BM1880AllocationsInfo::allocateWeightVars(const IRFunction *F) {

size_t weightOffset = 0;
// Compute the new offsets for all the weights, do not reuse their current
// addresses. Process all constant WeightVars first.
for (auto &v : F->getGraph()->getParent()->getConstants()) {
assert(isa<WeightVar>(F->getWeightForNode(v)));
auto *w = cast<WeightVar>(F->getWeightForNode(v));
auto numBytes = w->getSizeInBytes();
// size_t addr = constantWeightVarsAllocator.allocate(numBytes, w);
size_t addr = weightOffset;
weightOffset += numBytes;
allocatedAddressed_[w] = addr;

DEBUG_GLOW(llvm::errs() << "Allocated global weight " << w->getName()
<< " size: " << numBytes << " address range: ["
<< addr << ", " << addr + numBytes << "]\n");
}

// Remember that max required memory size for each kind of weights.
globa_weight_sizes_ = weightOffset;
}

void BM1880AllocationsInfo::allocateNeuron(WeightVar *W, size_t &neuronOffset) {
auto numBytes = W->getSizeInBytes();
// size_t addr = activationsAllocator.allocate(numBytes, w);
size_t addr = neuronOffset;
neuronOffset += numBytes;
allocatedAddressed_[W] = addr;

DEBUG_GLOW(llvm::errs() << "Allocated global input/output " << W->getName()
<< " size: " << numBytes << " address range: ["
<< addr << ", " << addr + numBytes << "]\n");
}

void BM1880AllocationsInfo::allocateActivations(const IRFunction *F) {
// Maps activations and views to some offset within the heap.
llvm::DenseMap<const Value *, uint64_t> activationAddr;

// global offset start from 0, input data need to start from 0
size_t neuronOffset = 0;
// allocate input
for (auto &v : F->getGraph()->getParent()->getPlaceholders()) {
assert(isa<WeightVar>(F->getWeightForNode(v)));
// unfortunately we need to use prefix to separate input/output
if (v->getName().find("save_") != llvm::StringRef::npos)
continue;

auto *w = cast<WeightVar>(F->getWeightForNode(v));
allocateNeuron(w, neuronOffset);
}

// alloc output.
for (auto &v : F->getGraph()->getParent()->getPlaceholders()) {
assert(isa<WeightVar>(F->getWeightForNode(v)));
if (v->getName().find("save_") == llvm::StringRef::npos)
continue;
auto *w = cast<WeightVar>(F->getWeightForNode(v));
allocateNeuron(w, neuronOffset);
}

global_neuron_sizes_ = neuronOffset;

MemoryAllocator activationsAllocator("activations",
TTI_->getLocalMemSizeInBytes());

// Assign device-space addresses to the activations.
for (auto &I : F->getInstrs()) {
if (auto *A = dyn_cast<AllocActivationInst>(&I)) {
// FIXME, getLMemSizeFromValue can not accept const variable currently
auto *nonConstI = const_cast<glow::Instruction *>(&I);
auto numBytes = TTI_->getLMemSizeFromValue(nonConstI);

// default MemoryAllocator is always 64-bytes aligned which has meet
// ours eu_num(16) alignment requirement
// TODO it's not efficieny for memory usage. support unaligned alloc
uint64_t addr = activationsAllocator.allocate(numBytes, A);
assert(!activationAddr.count(A) && "Allocation already made!");
assert(MemoryAllocator::npos != addr);
activationAddr[A] = addr;
continue;
}

if (auto *D = dyn_cast<DeallocActivationInst>(&I)) {
auto *A = D->getAlloc();
assert(activationAddr.count(A) && "Invalid deallocation!");
activationsAllocator.deallocate(A);
continue;
}
}

local_memory_sizes_ = activationsAllocator.getMaxMemoryUsage();

// Register specific addresses within the heap to activations.
for (auto &A : activationAddr) {
allocatedAddressed_[A.first] = A.second;
uint64_t size =
TTI_->getLMemSizeFromValue(const_cast<glow::Value *>(A.first));
DEBUG_GLOW(llvm::errs() << "Allocated activation " << A.first->getName()
<< " size: " << size << " address range: ["
<< allocatedAddressed_[A.first] << ", "
<< allocatedAddressed_[A.first] + size << "]\n";);
}
}

llvm::DenseMap<const Value *, uint64_t> &
BM1880AllocationsInfo::getAllocatedAddress() {
return allocatedAddressed_;
}

void BM1880AllocationsInfo::setActivationsMemSize(size_t v) {
global_neuron_sizes_ = v;
}

size_t BM1880AllocationsInfo::getActivationsMemSize() {
return global_neuron_sizes_;
}
50 changes: 50 additions & 0 deletions lib/Backends/Sophon/BM188x/BM1880AllocationsInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include "Backends/Sophon/AllocationsInfo.h"
#include "Backends/Sophon/SophonTargetTransformInfo.h"
#include "glow/CodeGen/MemoryAllocator.h"
#include "llvm/ADT/DenseMap.h"

namespace glow {

/// Information about allocations for activations, constant weight variables
/// and mutable weight variables.
class BM1880AllocationsInfo : public AllocationsInfo {

private:
void allocateNeuron(WeightVar *W, size_t &neuronOffset);

private:
/// Different kinds of values that need to be allocated.
enum class ValueKind { Global_Weight, Global_Neuron, Local_Memory };

/// Maps Values in the module to their offsets.
llvm::DenseMap<const Value *, uint64_t> allocatedAddressed_;
/// Amount of memory to be allocated for constant WeightVars.
size_t globa_weight_sizes_{0};
/// Amount of memory to be allocated for mutable WeightVars.
size_t global_neuron_sizes_{0};
/// Amount of memory to be allocated for activations.
size_t local_memory_sizes_{0};

const sophon::SophonTargetTransformInfo *TTI_;

public:
BM1880AllocationsInfo();
BM1880AllocationsInfo(const sophon::SophonTargetTransformInfo *TTI);
void allocateWeightVars(const IRFunction *F) override;
void allocateActivations(const IRFunction *F) override;
void allocateTensorViews(const IRFunction *F) override {
llvm_unreachable("unsupported!");
}
/// Number all allocations and weight variables by assigning them unique
/// numbers.
void numberValues(const IRFunction *F) override { llvm_unreachable("TODO!"); }

public:
llvm::DenseMap<const Value *, uint64_t> &getAllocatedAddress() override;
void setActivationsMemSize(size_t v) override;
size_t getActivationsMemSize() override;
};

} // namespace glow
Loading