| 336 | return *this; |
| 337 | } |
| 338 | bool test(MNNForwardType type, const std::string& device_name, const std::string& test_op_name, int batch, |
| 339 | int ic, int oc, int ih, int iw, PadMode mode, int pad_h, int pad_w, int kh, int kw, int stride, |
| 340 | int dilation, int group, int precision, MNN::SparseAlgo sparseAlgo = MNN::SparseAlgo_RANDOM, int sparseBlockOC = 1, bool debug = false, bool testRelu = false) { |
| 341 | using namespace MNN::Express; |
| 342 | std::map<PadMode, Express::PaddingMode> padMap = { |
| 343 | {PadMode_CAFFE, CAFFE}, {PadMode_VALID, VALID}, {PadMode_SAME, SAME}}; |
| 344 | std::vector<float> weightData, biasData; |
| 345 | |
| 346 | generateWeight(weightData, ic, oc, kh, kw, dilation, group, sparseBlockOC); |
| 347 | |
| 348 | for (int i = 0; i < oc; i++) { |
| 349 | auto data = (((i / kw) % 1317) * ((i / kh) % 1317) + i / ic + i / oc + (oc - i) * ic + i * (oc - i)) % 1317; |
| 350 | auto floatData = (float)(data % 255) / 255.0f; |
| 351 | data = data * data; |
| 352 | biasData.push_back(floatData); |
| 353 | // biasData.push_back(0.0f); |
| 354 | } |
| 355 | |
| 356 | std::vector<float> inputData, outputData, outputDataSeparateBias; |
| 357 | for (int i = 0; i < ih * iw * ic * batch; ++i) { |
| 358 | auto data = ((i / kw) % 1317) * ((i / kh) % 1317) + ((i / ic)% 1317) * ((i / oc) % 1317) + ((oc - i) % 1317) * ic + (i % 1317) * ((oc - i) % 1317); |
| 359 | data = data % 1317; |
| 360 | data = (data * data) % 1317; |
| 361 | auto floatData = (float)(data % 255) / 255.0f; |
| 362 | inputData.push_back(floatData); |
| 363 | } |
| 364 | reference_conv2d(inputData, weightData, biasData, outputData, outputDataSeparateBias, batch, ic, oc, ih, iw, mode, pad_h, pad_w, kh, kw, |
| 365 | stride, dilation, group, FP32Converter[precision]); |
| 366 | if (outputData.size() == 0) { |
| 367 | return true; |
| 368 | } |
| 369 | |
| 370 | auto input = _Input({batch, ic, ih, iw}, NCHW, halide_type_of<float>()); |
| 371 | ::memcpy(input->writeMap<float>(), inputData.data(), inputData.size() * sizeof(float)); |
| 372 | // Multi Conv |
| 373 | if (group == 1 || (group == ic && ic == oc)) { |
| 374 | VARP weightVar; |
| 375 | if (group == 1) { |
| 376 | weightVar = _Const(weightData.data(), {oc, ic, kh, kw}, NCHW, halide_type_of<float>()); |
| 377 | } else { |
| 378 | weightVar = _Const(weightData.data(), {oc, ic / group, kh, kw}, NCHW, halide_type_of<float>()); |
| 379 | } |
| 380 | auto biasVar = _Const(biasData.data(), {oc}, NCHW, halide_type_of<float>()); |
| 381 | auto out = _Conv(weightVar, biasVar, _Convert(input, NC4HW4), padMap[mode], {stride, stride}, {dilation, dilation}, group, |
| 382 | {pad_w, pad_h}, sparseAlgo, sparseBlockOC, mSparse); |
| 383 | out = _Convert(out, NCHW); |
| 384 | auto outputPtr = out->readMap<float>(); |
| 385 | if (!checkVectorByRelativeError<float>(outputPtr, outputData.data(), outputData.size(), 0.05)) { |
| 386 | MNN_PRINT("multi expect:\t real:\n"); |
| 387 | for (int i = 0; i < outputData.size(); ++i) |
| 388 | { |
| 389 | MNN_PRINT("%f\t, %f\n", outputData[i], outputPtr[i]); |
| 390 | } |
| 391 | MNN_ERROR("%s(%s) multi test failed, n=%d, oc=%d, oh=%d, ow=%d!\n", test_op_name.c_str(), device_name.c_str(), out->getInfo()->dim[0], out->getInfo()->dim[1], out->getInfo()->dim[2], out->getInfo()->dim[3]); |
| 392 | return false; |
| 393 | } |
| 394 | } |
| 395 | // Single Conv |