int test_layer_naive(int typeindex, const ncnn::ParamDict& pd, const std::vector<ncnn::Mat>& weights, const std::vector<ncnn::Mat>& a, int top_blob_count, std::vector<ncnn::Mat>& b, void (*func)(ncnn::Layer*), int flag)
{
ncnn::Layer* op = ncnn::create_layer_naive(typeindex);
int test_layer_oom_opt(const char* layer_type, const ncnn::ParamDict& pd, const std::vector<ncnn::Mat>& weights, const ncnn::Option& _opt, const std::vector<ncnn::Mat>& a, int top_blob_count, int flag)
{
int typeindex = ncnn::layer_to_index(layer_type);
if (typeindex == -1)
return -1;
ncnn::Layer* op = ncnn::create_layer_cpu(typeindex);
if (!op->support_packing && _opt.use_packing_layout)
{
delete op;
return 233;
}
if (!op->support_bf16_storage && !op->support_fp16_storage && (_opt.use_bf16_storage || _opt.use_fp16_arithmetic))
{
delete op;
return 233;
}
op->load_param(pd);
if (op->one_blob_only && a.size() != 1)
{
fprintf(stderr, "layer with one_blob_only but consume multiple inputs\n");
delete op;
return -1;
}
ncnn::ModelBinFromMatArray mb(weights.data());
op->load_model(mb);
ncnn::Option opt = _opt;
opt.num_threads = 1;
opt.use_vulkan_compute = false;
op->create_pipeline(opt);
if (!op->support_packing && _opt.use_packing_layout)
{
op->destroy_pipeline(opt);
delete op;
return 233;
}
if (!op->support_bf16_storage && !op->support_fp16_storage && (_opt.use_bf16_storage || _opt.use_fp16_arithmetic))
const int alloc_count = test_oom_allocator.counter;
for (int i = 0; i < alloc_count; i++)
{
test_oom_allocator.counter = 0;
test_oom_allocator.failid = i;
int ret = 0;
if (op->support_inplace)
{
for (size_t i = 0; i < a4.size(); i++)
{
c[i] = a4[i].clone();
}
ret = op->forward_inplace(c, opt);
}
else
{
ret = op->forward(a4, c, opt);
}
for (int i = 0; i < top_blob_count; i++)
{
c[i].release();
}
if (ret != -100)
{
fprintf(stderr, "oom not catched %d/%d\n", i, alloc_count);
op->destroy_pipeline(opt);
delete op;
return -1;
}
}
op->destroy_pipeline(opt);
delete op;
return 0;
}
int test_layer_oom_opt(const char* layer_type, const ncnn::ParamDict& pd, const std::vector<ncnn::Mat>& weights, const ncnn::Option& _opt, const ncnn::Mat& a, int flag)
{
int typeindex = ncnn::layer_to_index(layer_type);
if (typeindex == -1)
return -1;
ncnn::Layer* op = ncnn::create_layer_cpu(typeindex);
if (!op->support_packing && _opt.use_packing_layout)
{
delete op;
return 233;
}
if (!op->support_bf16_storage && !op->support_fp16_storage && (_opt.use_bf16_storage || _opt.use_fp16_arithmetic))
{
delete op;
return 233;
}
op->load_param(pd);
ncnn::ModelBinFromMatArray mb(weights.data());
op->load_model(mb);
ncnn::Option opt = _opt;
opt.num_threads = 1;
opt.use_vulkan_compute = false;
op->create_pipeline(opt);
if (!op->support_packing && _opt.use_packing_layout)
{
op->destroy_pipeline(opt);
delete op;
return 233;
}
if (!op->support_bf16_storage && !op->support_fp16_storage && (_opt.use_bf16_storage || _opt.use_fp16_arithmetic))
{
op->destroy_pipeline(opt);
delete op;
return 233;
}
ncnn::Mat a4;
convert_to_optimal_layout(a, a4, opt, op, flag);
TestOOMAllocator test_oom_allocator;
opt.blob_allocator = &test_oom_allocator;
opt.workspace_allocator = &test_oom_allocator;
ncnn::Mat c;
if (op->support_inplace)
{
c = a4.clone();
op->forward_inplace(c, opt);
}
else
{
op->forward(a4, c, opt);
}
c.release();
const int alloc_count = test_oom_allocator.counter;
for (int i = 0; i < alloc_count; i++)
{
test_oom_allocator.counter = 0;
test_oom_allocator.failid = i;
int ret = 0;
if (op->support_inplace)
{
c = a4.clone();
ret = op->forward_inplace(c, opt);
}
else
{
ret = op->forward(a4, c, opt);
}
c.release();
if (ret != -100)
{
fprintf(stderr, "oom not catched %d/%d\n", i, alloc_count);
op->destroy_pipeline(opt);
delete op;
return -1;
}
}
op->destroy_pipeline(opt);
delete op;
return 0;
}
int test_layer_oom(const char* layer_type, const ncnn::ParamDict& pd, const std::vector<ncnn::Mat>& weights, const std::vector<ncnn::Mat>& a, int top_blob_count, int flag)
{
// pack fp16p fp16s fp16a bf16s shader8 image
const int options[][7] = {
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 0, 0},
{1, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 1, 0, 0},
{1, 0, 1, 0, 0, 1, 0},
{1, 1, 1, 1, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 1},
};
const int opt_count = sizeof(options) / sizeof(options[0]);
for (int i = 0; i < opt_count; i++)
{
ncnn::Option opt;
opt.num_threads = 1;
opt.use_packing_layout = options[i][0];
opt.use_fp16_packed = options[i][1];
opt.use_fp16_storage = options[i][2];
opt.use_fp16_arithmetic = options[i][3];
opt.use_bf16_storage = options[i][4];
opt.use_shader_pack8 = options[i][5];
opt.use_image_storage = options[i][6];
int ret = test_layer_oom_opt(layer_type, pd, weights, opt, a, top_blob_count, flag);
if (ret != 233 && ret != 0)
return ret;
}
return 0;
}
int test_layer_oom(const char* layer_type, const ncnn::ParamDict& pd, const std::vector<ncnn::Mat>& weights, const ncnn::Mat& a, int flag)
{
// pack fp16p fp16s fp16a bf16s shader8 image
const int options[][7] = {
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 0, 0},
{1, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 1, 0, 0},
{1, 0, 1, 0, 0, 1, 0},
{1, 1, 1, 1, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 1},
};
const int opt_count = sizeof(options) / sizeof(options[0]);
for (int i = 0; i < opt_count; i++)
{
ncnn::Option opt;
opt.num_threads = 1;
opt.use_packing_layout = options[i][0];
opt.use_fp16_packed = options[i][1];
opt.use_fp16_storage = options[i][2];
opt.use_fp16_arithmetic = options[i][3];
opt.use_bf16_storage = options[i][4];
opt.use_shader_pack8 = options[i][5];
opt.use_image_storage = options[i][6];
int ret = test_layer_oom_opt(layer_type, pd, weights, opt, a, flag);
int test_layer(const char* layer_type, const ncnn::ParamDict& pd, const std::vector<ncnn::Mat>& weights, const ncnn::Mat& a, float epsilon = 0.001, void (*func)(ncnn::Layer*) = 0, int flag = 0);
// oom test
int test_layer_oom_opt(const char* layer_type, const ncnn::ParamDict& pd, const std::vector<ncnn::Mat>& weights, const ncnn::Option& opt, const std::vector<ncnn::Mat>& a, int top_blob_count = 1, int flag = 0);
int test_layer_oom_opt(const char* layer_type, const ncnn::ParamDict& pd, const std::vector<ncnn::Mat>& weights, const ncnn::Option& opt, const ncnn::Mat& a, int flag = 0);
int test_layer_oom(const char* layer_type, const ncnn::ParamDict& pd, const std::vector<ncnn::Mat>& weights, const std::vector<ncnn::Mat>& a, int top_blob_count = 1, int flag = 0);
int test_layer_oom(const char* layer_type, const ncnn::ParamDict& pd, const std::vector<ncnn::Mat>& weights, const ncnn::Mat& a, int flag = 0);