Unverified Commit e11a6092 by Liangfu Chen Committed by GitHub

[uTVM][Runtime] Introduce Virtual Memory Allocator to CRT (#5124)

* initial crt_memory and memory leak fix in graph_runtime

Change-Id: I0f79f909a04d1c677aabb80f202f0612c5ce7f2a

* fix memory leak

Change-Id: I37104c09e28112b1974fa2b064c809d0a8d686c3

* clean up

Change-Id: I039b12015a1d56c8f4120867cd5a5292da34f3e3

* implement vrealloc

Change-Id: I35800470bcbfcf96652494f359711cb4c2d34398

* allocate from stack memory for most of the variables

Change-Id: I72071289843fff4031c0df8796868a0b9fbc57ee

* allocate from stack memory for all of the variables

Change-Id: I32dba85ac1660c77f51c2d0d8ab6436ed0c01c74

* lint

Change-Id: If12cd240685d7791fc60bc0cfb66389cdc186b73

* lint

Change-Id: I7c9d90c11b60b8edda2427ebd189ebe535af2100

* facilitate the growth of TVM_CRT_MAX_NDIM

Change-Id: I939fa43027a5c7529c5c7c6bd8d6e6beb91b7581

* extend test coverage of vmalloc

Change-Id: Ie4ff6b64fdfe6810836cf8fd44dace82a20c4581

* lint

Change-Id: Ibf3c06619ef296df5c49f3945cb6428777781d69

* move logging.h to src

* fix an error in macOS

* remove logging.h

* use cflags for gcc

* fix compilation error
parent f5b02fdb
......@@ -20,11 +20,11 @@
# Setup build environment
TVM_ROOT=$(shell cd ../..; pwd)
DMLC_CORE=${TVM_ROOT}/3rdparty/dmlc-core
PKG_CXXFLAGS = -std=c++14 -O2 -fPIC \
PKG_CXXFLAGS = -Wall -std=c++14 -O2 -fPIC \
-I${TVM_ROOT}/include \
-I${DMLC_CORE}/include \
-I${TVM_ROOT}/3rdparty/dlpack/include
PKG_CFLAGS = -std=c99 -O2 -fPIC \
PKG_CFLAGS = -Wall -std=c99 -O2 -fPIC \
-I${TVM_ROOT}/include \
-I${DMLC_CORE}/include \
-I${TVM_ROOT}/3rdparty/dlpack/include
......@@ -57,11 +57,11 @@ $(build_dir)/test_dynamic: test.cc ${build_dir}/test_graph.json ${build_dir}/tes
$(build_dir)/demo_static: demo_static.c ${build_dir}/bundle_static.o ${build_dir}/model.o ${build_dir}/graph.json.c ${build_dir}/params.bin.c
@mkdir -p $(@D)
gcc $(PKG_CXXFLAGS) -o $@ demo_static.c ${build_dir}/bundle_static.o ${build_dir}/model.o -lm
gcc $(PKG_CFLAGS) -o $@ demo_static.c ${build_dir}/bundle_static.o ${build_dir}/model.o -lm
$(build_dir)/test_static: test_static.c ${build_dir}/bundle_static.o ${build_dir}/test_model.o
@mkdir -p $(@D)
gcc $(PKG_CXXFLAGS) -o $@ $^
gcc $(PKG_CFLAGS) -o $@ $^
# Serialize our graph.json file.
$(build_dir)/graph.json.c: $(build_dir)/graph.json
......@@ -71,14 +71,6 @@ $(build_dir)/graph.json.c: $(build_dir)/graph.json
$(build_dir)/params.bin.c: $(build_dir)/params.bin
xxd -i $^ > $@
# # Serialize our test_graph.json file.
# $(build_dir)/test_graph.json.c: $(build_dir)/test_graph.json
# xxd -i $^ > $@
#
# # Serialize our test_params.bin file.
# $(build_dir)/test_params.bin.c: $(build_dir)/test_params.bin
# xxd -i $^ > $@
$(build_dir)/model.o $(build_dir)/graph.json $(build_dir)/params.bin $(build_dir)/cat.bin: build_model.py
python3 $< -o $(build_dir)
......
......@@ -109,11 +109,11 @@ int main(int argc, char **argv) {
max_index, max_iter);
printf("timing: %.2f ms (create), %.2f ms (set_input), %.2f ms (run), "
"%.2f ms (get_output), %.2f ms (destroy)\n",
(t1.tv_sec-t0.tv_sec)*1000000 + (t1.tv_usec-t0.tv_usec)/1000.f,
(t2.tv_sec-t1.tv_sec)*1000000 + (t2.tv_usec-t1.tv_usec)/1000.f,
(t3.tv_sec-t2.tv_sec)*1000000 + (t3.tv_usec-t2.tv_usec)/1000.f,
(t4.tv_sec-t3.tv_sec)*1000000 + (t4.tv_usec-t3.tv_usec)/1000.f,
(t5.tv_sec-t4.tv_sec)*1000000 + (t5.tv_usec-t4.tv_usec)/1000.f);
(t1.tv_sec-t0.tv_sec)*1000.0f + (t1.tv_usec-t0.tv_usec)/1000.f,
(t2.tv_sec-t1.tv_sec)*1000.0f + (t2.tv_usec-t1.tv_usec)/1000.f,
(t3.tv_sec-t2.tv_sec)*1000.0f + (t3.tv_usec-t2.tv_usec)/1000.f,
(t4.tv_sec-t3.tv_sec)*1000.0f + (t4.tv_usec-t3.tv_usec)/1000.f,
(t5.tv_sec-t4.tv_sec)*1000.0f + (t5.tv_usec-t4.tv_usec)/1000.f);
dlclose(bundle);
return 0;
......
......@@ -30,23 +30,37 @@
#define TVM_CRT_MAX_NDIM 6
/*! Maximum supported arguments in generated functions */
#define TVM_CRT_MAX_ARGS 10
/*! Maximum supported string length in dltype, e.g. "int8", "int16", "float32" */
#define TVM_CRT_STRLEN_DLTYPE 10
/*! Maximum supported string length in function names */
#define TVM_CRT_STRLEN_NAME 80
/*! Maximum inputs in a GraphRuntimeNode */
#define GRAPH_RUNTIME_NODE_MAX_INPUTS 300
/*! Maximum supported contexts in a GraphRuntime */
#define GRAPH_RUNTIME_MAX_CONTEXTS 1
/*! Maximum supported nodes in a GraphRuntime */
#define GRAPH_RUNTIME_MAX_NODES 400
/*! Maximum input nodes in a GraphRuntime */
#define GRAPH_RUNTIME_MAX_INPUT_NODES 300
/*! Maximum nodes in a GraphRuntime for quick entry indexing */
#define GRAPH_RUNTIME_MAX_NODE_ROW_PTR 300
/*! Maximum output entries in a GraphRuntime */
#define GRAPH_RUNTIME_MAX_OUTPUTS 300
/*!
* \brief Log memory pool size for virtual memory allocation
*
* Here is a list of possible choices:
* * use 16 for 64 KiB memory space
* * use 17 for 128 KiB memory space
* * use 18 for 256 KiB memory space
* * use 19 for 512 KiB memory space
* * use 20 for 1 MiB memory space
* * use 21 for 2 MiB memory space
* * use 22 for 4 MiB memory space
* * use 23 for 8 MiB memory space
* * use 24 for 16 MiB memory space
* * use 25 for 32 MiB memory space
* * use 26 for 64 MiB memory space
* * use 27 for 128 MiB memory space
* * use 28 for 256 MiB memory space
*/
#define TVM_CRT_LOG_VIRT_MEM_SIZE 24
/*! \brief Page size for virtual memory allocation */
#define TVM_CRT_PAGE_BYTES 4096
#include "../../src/runtime/crt/crt_runtime_api.c"
#include "../../src/runtime/crt/crt_backend_api.c"
#include "../../src/runtime/crt/graph_runtime.c"
#include "../../src/runtime/crt/load_json.c"
#include "../../src/runtime/crt/ndarray.c"
#include "../../src/runtime/crt/memory.c"
......@@ -122,11 +122,11 @@ int main(int argc, char **argv) {
printf("timing: %.2f ms (create), %.2f ms (set_input), %.2f ms (run), "
"%.2f ms (get_output), %.2f ms (destroy)\n",
(t1.tv_sec-t0.tv_sec)*1000000 + (t1.tv_usec-t0.tv_usec)/1000.f,
(t2.tv_sec-t1.tv_sec)*1000000 + (t2.tv_usec-t1.tv_usec)/1000.f,
(t3.tv_sec-t2.tv_sec)*1000000 + (t3.tv_usec-t2.tv_usec)/1000.f,
(t4.tv_sec-t3.tv_sec)*1000000 + (t4.tv_usec-t3.tv_usec)/1000.f,
(t5.tv_sec-t4.tv_sec)*1000000 + (t5.tv_usec-t4.tv_usec)/1000.f);
(t1.tv_sec-t0.tv_sec)*1000.0f + (t1.tv_usec-t0.tv_usec)/1000.f,
(t2.tv_sec-t1.tv_sec)*1000.0f + (t2.tv_usec-t1.tv_usec)/1000.f,
(t3.tv_sec-t2.tv_sec)*1000.0f + (t3.tv_usec-t2.tv_usec)/1000.f,
(t4.tv_sec-t3.tv_sec)*1000.0f + (t4.tv_usec-t3.tv_usec)/1000.f,
(t5.tv_sec-t4.tv_sec)*1000.0f + (t5.tv_usec-t4.tv_usec)/1000.f);
free(json_data);
free(params_data);
......
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/*!
* \file tvm/runtime/crt/memory.h
* \brief The virtual memory manager for micro-controllers
*/
#ifndef TVM_RUNTIME_CRT_MEMORY_H_
#define TVM_RUNTIME_CRT_MEMORY_H_
static int vleak_size = 0;
/*!
* \brief Allocate memory from manager
* \param size The size of memory
* \return The virtual address
*/
void * vmalloc(size_t size);
/*!
* \brief Reallocate memory from manager
* \param ptr The pointer to the memory area to be reallocated
* \param size The size of memory
* \return The virtual address
*/
void * vrealloc(void * ptr, size_t size);
/*!
* \brief Free the memory.
* \param ptr The pointer to the memory to deallocate
* \return The virtual address
*/
void vfree(void * ptr);
#endif // TVM_RUNTIME_CRT_MEMORY_H_
......@@ -18,6 +18,7 @@
*/
#include <tvm/runtime/c_backend_api.h>
#include <tvm/runtime/crt/memory.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -29,18 +30,12 @@ void* TVMBackendAllocWorkspace(int device_type, int device_id, uint64_t nbytes,
void* ptr = 0;
assert(nbytes > 0);
unsigned int dtype_bytes = dtype_bits_hint / 8;
#ifdef __ANDROID__
ptr = memalign(64, nbytes * dtype_bytes);
#else
const int ret = posix_memalign(&ptr, 64, nbytes * dtype_bytes);
(void)ret;
assert(ret == 0);
#endif
ptr = vmalloc(nbytes * dtype_bytes);
return ptr;
}
int TVMBackendFreeWorkspace(int device_type, int device_id, void* ptr) {
free(ptr);
vfree(ptr);
return 0;
}
......@@ -52,6 +47,7 @@ int TVMBackendParallelLaunch(FTVMParallelLambda flambda, void* cdata, int num_ta
}
int TVMBackendRegisterSystemLibSymbol(const char* name, void* ptr) {
g_fexecs = vrealloc(g_fexecs, sizeof(TVMPackedFunc) * (g_fexecs_count + 1));
snprintf(g_fexecs[g_fexecs_count].name, sizeof(g_fexecs[g_fexecs_count].name), name);
g_fexecs[g_fexecs_count].fexec = ptr;
g_fexecs_count++;
......
......@@ -63,10 +63,11 @@ typedef struct TVMGraphRuntimeNode {
// parameters
TVMOpParam param;
// inputs
TVMGraphRuntimeNodeEntry inputs[GRAPH_RUNTIME_NODE_MAX_INPUTS];
size_t inputs_count;
TVMGraphRuntimeNodeEntry * inputs;
// number of inputs
size_t inputs_count;
// control deps
uint32_t control_deps[200];
uint32_t control_deps[20];
// JSON Loader
void (*LoadAttrs)(struct TVMGraphRuntimeNode * node, JSONReader *reader, TVMOpParam* param);
// JSON Loader
......@@ -76,12 +77,12 @@ typedef struct TVMGraphRuntimeNode {
// Graph attribute
typedef struct TVMGraphRuntimeGraphAttr {
uint32_t storage_num_not_alloctaed;
uint32_t storage_id[GRAPH_RUNTIME_MAX_NODES];
uint32_t device_index[GRAPH_RUNTIME_MAX_NODES];
char dltype[GRAPH_RUNTIME_MAX_NODES][10]; // "int8", "int16", "float32"
uint32_t * storage_id;
uint32_t * device_index;
char * dltype; // "int8", "int16", "float32"
uint32_t dltype_count;
int64_t shape[GRAPH_RUNTIME_MAX_NODES][TVM_CRT_MAX_NDIM];
uint32_t ndim[GRAPH_RUNTIME_MAX_NODES];
int64_t * shape;
uint32_t * ndim;
uint32_t shape_count;
} TVMGraphRuntimeGraphAttr;
......@@ -169,33 +170,35 @@ typedef struct TVMGraphRuntime {
// Get node entry index.
uint32_t (*GetEntryId)(struct TVMGraphRuntime * runtime, uint32_t nid, uint32_t index);
// /*! \brief The graph nodes. */
TVMGraphRuntimeNode nodes[GRAPH_RUNTIME_MAX_NODES];
uint32_t nodes_count;
/*! \brief The graph nodes. */
TVMGraphRuntimeNode * nodes;
/*! \brief The graph nodes counter. */
uint32_t nodes_count;
/*! \brief The argument nodes. */
uint32_t input_nodes[GRAPH_RUNTIME_MAX_INPUT_NODES];
uint32_t input_nodes_count;
uint32_t * input_nodes;
uint32_t input_nodes_count;
/*! \brief Used for quick entry indexing. */
uint32_t node_row_ptr[GRAPH_RUNTIME_MAX_NODE_ROW_PTR];
uint32_t * node_row_ptr;
uint32_t node_row_ptr_count;
/*! \brief Output entries. */
TVMGraphRuntimeNodeEntry outputs[GRAPH_RUNTIME_MAX_OUTPUTS];
uint32_t outputs_count;
TVMGraphRuntimeNodeEntry * outputs;
/*! \brief Output entries counter. */
uint32_t outputs_count;
/*! \brief Additional graph attributes. */
TVMGraphRuntimeGraphAttr attrs;
/*! \brief The code module that contains both host and device code. */
TVMModule module;
/*! \brief Execution context of all devices including the host. */
TVMContext ctxs[GRAPH_RUNTIME_MAX_CONTEXTS];
TVMContext ctxs[1];
uint32_t ctxs_count;
/*! \brief Common storage pool for all devices. */
TVMNDArray storage_pool[GRAPH_RUNTIME_MAX_NODES];
TVMNDArray * storage_pool;
uint32_t storage_pool_count;
/*! \brief Data entry of each node. */
TVMNDArray data_entry[GRAPH_RUNTIME_MAX_NODES];
TVMNDArray * data_entry;
uint32_t data_entry_count;
/*! \brief Operator on each node. */
TVMPackedFunc op_execs[GRAPH_RUNTIME_MAX_NODES];
TVMPackedFunc * op_execs;
uint32_t op_execs_count;
} TVMGraphRuntime;
......
......@@ -21,6 +21,8 @@
* \file load_json.c
* \brief Load graph from JSON file.
*/
#include <tvm/runtime/crt/memory.h>
#include "load_json.h"
// the node entry structure in serialized format
......@@ -74,10 +76,10 @@ void SeqPop(Seq * seq) {
}
Seq * SeqCreate(uint64_t len) {
Seq * seq = (Seq*)malloc(sizeof(Seq)); // NOLINT(*)
Seq * seq = (Seq*)vmalloc(sizeof(Seq)); // NOLINT(*)
memset(seq, 0, sizeof(Seq));
seq->allocated = len;
seq->data = (uint32_t*)malloc(sizeof(uint32_t)*len); // NOLINT(*)
seq->data = (uint32_t*)vmalloc(sizeof(uint32_t)*len); // NOLINT(*)
seq->push_back = SeqPush;
seq->back = SeqBack;
seq->pop_back = SeqPop;
......@@ -85,8 +87,8 @@ Seq * SeqCreate(uint64_t len) {
}
void SeqRelease(Seq ** seq) {
free((*seq)->data);
free(*seq);
vfree((*seq)->data);
vfree(*seq);
}
......@@ -156,11 +158,11 @@ int JSONReader_ReadString(JSONReader * reader, char * out_str) {
if (ch == '\\') {
char sch = reader->NextChar(reader);
switch (sch) {
case 'r': snprintf(output, sizeof(output), "%s\r", output); break;
case 'n': snprintf(output, sizeof(output), "%s\n", output); break;
case '\\': snprintf(output, sizeof(output), "%s\\", output); break;
case 't': snprintf(output, sizeof(output), "%s\t", output); break;
case '\"': snprintf(output, sizeof(output), "%s\"", output); break;
case 'r': snprintf(output + strlen(output), sizeof(output), "\r"); break;
case 'n': snprintf(output + strlen(output), sizeof(output), "\n"); break;
case '\\': snprintf(output + strlen(output), sizeof(output), "\\"); break;
case 't': snprintf(output + strlen(output), sizeof(output), "\t"); break;
case '\"': snprintf(output + strlen(output), sizeof(output), "\""); break;
default: fprintf(stderr, "unknown string escape %c\n", sch);
}
} else {
......@@ -346,7 +348,7 @@ JSONReader JSONReader_Create(const char * is) {
reader.BeginObject = JSONReader_BeginObject;
reader.NextArrayItem = JSONReader_NextArrayItem;
reader.NextObjectItem = JSONReader_NextObjectItem;
reader.is_ = (char*)malloc(strlen(is)+1); // NOLINT(*)
reader.is_ = (char*)vmalloc(strlen(is)+1); // NOLINT(*)
memset(reader.is_, 0, strlen(is)+1);
snprintf(reader.is_, strlen(is)+1, "%s", is);
reader.isptr = reader.is_;
......@@ -355,5 +357,5 @@ JSONReader JSONReader_Create(const char * is) {
void JSONReader_Release(JSONReader * reader) {
SeqRelease(&(reader->scope_counter_));
free(reader->is_);
vfree(reader->is_);
}
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/*!
* \file runtime/crt/loggin.h
* \brief A replacement of the dmlc logging system that avoids
* the usage of GLOG and C++ headers
*/
#ifndef TVM_RUNTIME_CRT_LOGGING_H_
#define TVM_RUNTIME_CRT_LOGGING_H_
#ifndef CHECK
#define CHECK(x) \
do { \
if (!(x)) { \
fprintf(stderr, "Check failed: %s\n", #x); \
exit(-1); \
} \
}while(0)
#endif
#ifndef CHECK_BINARY_OP
#define CHECK_BINARY_OP(op, x, y, fmt, ...) \
do { \
if (!(x op y)) { \
fprintf(stderr, "Check failed: %s %s %s: " fmt "\n", #x, #op, #y, ##__VA_ARGS__); \
exit(-1); \
} \
}while(0)
#endif
#ifndef CHECK_LT
#define CHECK_LT(x, y, fmt, ...) CHECK_BINARY_OP(<, x, y, fmt, ##__VA_ARGS__)
#endif
#ifndef CHECK_GT
#define CHECK_GT(x, y, fmt, ...) CHECK_BINARY_OP(>, x, y, fmt, ##__VA_ARGS__)
#endif
#ifndef CHECK_LE
#define CHECK_LE(x, y, fmt, ...) CHECK_BINARY_OP(<=, x, y, fmt, ##__VA_ARGS__)
#endif
#ifndef CHECK_GE
#define CHECK_GE(x, y, fmt, ...) CHECK_BINARY_OP(>=, x, y, fmt, ##__VA_ARGS__)
#endif
#ifndef CHECK_EQ
#define CHECK_EQ(x, y, fmt, ...) CHECK_BINARY_OP(==, x, y, fmt, ##__VA_ARGS__)
#endif
#ifndef CHECK_NE
#define CHECK_NE(x, y, fmt, ...) CHECK_BINARY_OP(!=, x, y, fmt, ##__VA_ARGS__)
#endif
#endif // TVM_RUNTIME_CRT_LOGGING_H_
......@@ -24,11 +24,10 @@
#ifndef TVM_RUNTIME_CRT_MODULE_H_
#define TVM_RUNTIME_CRT_MODULE_H_
#include <string.h>
#include <tvm/runtime/c_runtime_api.h>
#include <string.h>
struct TVMPackedFunc;
typedef struct TVMPackedFunc TVMPackedFunc;
/*!
* \brief Module container of TVM.
......@@ -42,7 +41,7 @@ typedef struct TVMModule {
*
* This function will return PackedFunc(nullptr) if function do not exist.
*/
void (*GetFunction)(const char * name, TVMPackedFunc * pf);
void (*GetFunction)(struct TVMModule * mod, const char * name, struct TVMPackedFunc * pf);
} TVMModule;
#endif // TVM_RUNTIME_CRT_MODULE_H_
......@@ -22,6 +22,8 @@
* \brief NDArray container infratructure.
*/
#include <tvm/runtime/crt/memory.h>
#include "ndarray.h"
TVMNDArray TVMNDArray_Create(uint32_t ndim, const tvm_index_t * shape,
......@@ -29,7 +31,7 @@ TVMNDArray TVMNDArray_Create(uint32_t ndim, const tvm_index_t * shape,
TVMNDArray ret;
memset(&ret, 0, sizeof(TVMNDArray));
ret.dl_tensor.ndim = ndim;
ret.dl_tensor.shape = (int64_t*)malloc(sizeof(int64_t)*ndim); // NOLINT(*)
ret.dl_tensor.shape = (int64_t*)vmalloc(sizeof(int64_t)*ndim); // NOLINT(*)
memcpy(ret.dl_tensor.shape, shape, sizeof(int64_t)*ndim);
ret.dl_tensor.dtype = dtype;
ret.dl_tensor.ctx = ctx;
......@@ -109,7 +111,9 @@ TVMNDArray TVMNDArray_CreateView(TVMNDArray * arr, const tvm_index_t * shape,
}
int TVMNDArray_Release(TVMNDArray * arr) {
free(arr->dl_tensor.data);
free(arr->dl_tensor.shape);
vfree(arr->dl_tensor.data);
arr->dl_tensor.data = 0;
vfree(arr->dl_tensor.shape);
arr->dl_tensor.shape = 0;
return 0;
}
......@@ -112,14 +112,12 @@ static inline void TVMPackedFunc_SetArgs(TVMPackedFunc * pf, const TVMArgs * arg
memcpy(&(pf->args), args, sizeof(TVMArgs));
}
TVMPackedFunc g_fexecs[GRAPH_RUNTIME_MAX_NODES];
TVMPackedFunc * g_fexecs = 0;
uint32_t g_fexecs_count = 0;
void TVMPackedFunc_SetupExecs();
// Implement TVMModule::GetFunction
// Put implementation in this file so we have seen the TVMPackedFunc
static inline void TVMModule_GetFunction(const char * name, TVMPackedFunc * pf) {
static inline void TVMModule_GetFunction(TVMModule * mod, const char * name, TVMPackedFunc * pf) {
int idx;
memset(pf, 0, sizeof(TVMPackedFunc));
assert(strlen(name) <= sizeof(pf->name));
......@@ -127,13 +125,13 @@ static inline void TVMModule_GetFunction(const char * name, TVMPackedFunc * pf)
pf->Call = TVMPackedFunc_Call;
pf->SetArgs = TVMPackedFunc_SetArgs;
pf->fexec = &TVMNoOperation;
for (idx = 0; idx < GRAPH_RUNTIME_MAX_NODES; idx++) {
for (idx = 0; idx < g_fexecs_count; idx++) {
if (!strcmp(g_fexecs[idx].name, name)) {
pf->fexec = g_fexecs[idx].fexec;
break;
}
}
if (idx == GRAPH_RUNTIME_MAX_NODES) {
if (idx == g_fexecs_count) {
fprintf(stderr, "function handle for %s not found\n", name);
}
}
......
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#define TVM_CRT_LOG_VIRT_MEM_SIZE 16
#define TVM_CRT_PAGE_BYTES 4096
#include <gtest/gtest.h>
#include <tvm/runtime/crt/memory.h>
#include "../../src/runtime/crt/memory.c"
TEST(CRTMemory, Alloc) {
for (int idx = 0; idx < 65536; idx++) {
void * a = vmalloc(1);
EXPECT_EQ(vleak_size, 1);
vfree(a);
EXPECT_EQ(vleak_size, 0);
}
}
TEST(CRTMemory, Realloc) {
for (int idx = 0; idx < 65536; idx++) {
void * a = vrealloc(0, 1);
EXPECT_EQ(vleak_size, 1);
void * b = vrealloc(a, 1);
EXPECT_EQ(a, b);
EXPECT_EQ(vleak_size, 1);
vfree(a);
EXPECT_EQ(vleak_size, 0);
}
}
int main(int argc, char ** argv) {
testing::InitGoogleTest(&argc, argv);
testing::FLAGS_gtest_death_test_style = "threadsafe";
return RUN_ALL_TESTS();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment