运行 make test-cpp
,通过所有测例即为完成作业,每个测例 10 分。
- test_allocator:依赖作业一
- test_cast:依赖作业四
- test_clip:依赖作业三
- test_concat:依赖作业五
- test_element_wise:依赖作业六
- test_transpose:依赖作业二
- test_nativecpu_concat:依赖作业一、作业五
- test_nativecpu_elementwise:依赖作业一、作业六
- test_nativecpu_transpose:依赖作业一、作业二
- test_matmul:依赖作业六、作业七
- test_graph:依赖作业八
难度:⭐⭐⭐⭐
对应测例:test_allocator
,test_nativecpu_concat
,test_nativecpu_elementwise
,test_nativecpu_transpose
需要实现的代码块位置:include/core/allocator.h
// =================================== 作业 ===================================
// TODO:可能需要设计一个数据结构来存储free block,以便于管理和合并
// HINT: 可以使用一个 map 来存储 free block,key 为 block 的起始/结尾地址,value 为 block 的大小
// =================================== 作业 ===================================
需要实现的代码块位置:src/core/allocator.cc
完善分配函数:
size_t Allocator::alloc(size_t size)
{
IT_ASSERT(this->ptr == nullptr);
// pad the size to the multiple of alignment
size = this->getAlignedSize(size);
// =================================== 作业 ===================================
// TODO: 设计一个算法来分配内存,返回起始地址偏移量
// =================================== 作业 ===================================
return 0;
}
完善释放函数:
void Allocator::free(size_t addr, size_t size)
{
IT_ASSERT(this->ptr == nullptr);
size = getAlignedSize(size);
// =================================== 作业 ===================================
// TODO: 设计一个算法来回收内存
// =================================== 作业 ===================================
}
需要实现的代码块位置:src/core/graph.cc
完善计算图的内存分配部分:
void GraphObj::dataMalloc()
{
// topological sorting first
IT_ASSERT(topo_sort() == true);
// =================================== 作业 ===================================
// TODO:利用 allocator 给计算图分配内存
// HINT: 获取分配好的内存指针后,可以调用 tensor 的 setDataBlob 函数给 tensor 绑定内存
// =================================== 作业 ===================================
allocator.info();
}
难度:⭐
对应测例:test_transpose
,test_nativecpu_transpose
需要实现的代码块位置:src/operators/transpose.cc
optional<vector<Shape>> TransposeObj::inferShape(const TensorVec &inputs)
{
const auto A = inputs[0];
auto input_dim = A->getDims();
auto output_dim = input_dim;
int rank = A->getRank();
// =================================== 作业 ===================================
// TODO:修改 output_dim,返回正确的 transpose 后的 shape
// REF: https://onnx.ai/onnx/operators/onnx__Transpose.html#transpose-21
// =================================== 作业 ===================================
return std::nullopt;
}
难度:⭐
对应测例:test_clip
需要实现的代码块位置:src/operators/unary.cc
optional<vector<Shape>> ClipObj::inferShape(const TensorVec &inputs)
{
// =================================== 作业 ===================================
// TODO:返回经过 clip 操作后的 shape
// REF: https://onnx.ai/onnx/operators/onnx__Clip.html#clip-13
// =================================== 作业 ===================================
return std::nullopt;
}
难度:⭐⭐
对应测例:test_cast
需要实现的代码块位置:src/operators/unary.cc
vector<DataType> CastObj::inferDataType(const TensorVec &inputs) const
{
// =================================== 作业 ===================================
// TODO:返回经过 cast 操作后, 输出 tensor 的数目和数据类型
// REF_FILE: src/core/operator.cc
// REF: https://onnx.ai/onnx/operators/onnx__Cast.html#cast-21
// =================================== 作业 ===================================
return {};
}
optional<vector<Shape>> CastObj::inferShape(const TensorVec &inputs)
{
// =================================== 作业 ===================================
// TODO:返回经过 cast 操作后的 shape
// REF: https://onnx.ai/onnx/operators/onnx__Cast.html#cast-21
// =================================== 作业 ===================================
return std::nullopt;
}
难度:⭐⭐
对应测例:test_concat
,test_nativecpu_concat
需要实现的代码块位置:src/operators/concat.cc
optional<vector<Shape>> ConcatObj::inferShape(const TensorVec &inputs) {
Shape dims = inputs[0]->getDims();
auto rank = inputs[0]->getRank();
// =================================== 作业 ===================================
// TODO:修改 dims,返回正确的 concat 后的 shape
// REF: https://onnx.ai/onnx/operators/onnx__Concat.html#concat-13
// =================================== 作业 ===================================
return {{dims}};
}
难度:⭐⭐⭐
对应测例:test_element_wise
,test_nativecpu_elementwise
,test_matmul
需要实现的代码块位置:src/utils/operator_utils.cc
Shape infer_broadcast(const Shape &A, const Shape &B) {
// =================================== 作业 ===================================
// TODO:对 A 和 B 进行双向广播,返回广播后的形状。
// REF: https://github.com/onnx/onnx/blob/main/docs/Broadcasting.md
// =================================== 作业 ===================================
return {};
}
难度:⭐⭐⭐
对应测例:test_matmul
需要实现的代码块位置:src/operators/matmul.cc
optional<vector<Shape>> MatmulObj::inferShape(const TensorVec &inputs)
{
// =================================== 作业 ===================================
// TODO:返回经过 matmul 操作后的 shape
// REF: https://github.com/onnx/onnx/blob/main/docs/Operators.md#gemm
// =================================== 作业 ===================================
return std::nullopt;
}
难度:⭐⭐⭐⭐
对应测例:test_graph
需要实现的代码块位置:src/core/graph.cc
void GraphObj::optimize()
{
// =================================== 作业 ===================================
// TODO: 设计一个算法来实现指定的图优化规则
// 图优化规则如下:
// 1. 去除冗余的算子(例如,两个相邻的算子都是 transpose 算子,且做的是相反的操作,可以将其全部删除)
// 2. 合并算子(例如,矩阵乘算子中含有属性transA、transB,如果其输入存在transpose,且对最后两个维度做交换,就可以将transpose融入到矩阵乘算子的属性中去)
// =================================== 作业 ===================================
}