У даній статті ми детально розглянемо процес перетворення коду з платформи ARM, використовуючи інтегровані функції, на платформу x86/x64 Windows. Зокрема, ми зосередимося на конвертації функції, яка використовує ARM Neon інтрукції, у її еквівалент для Windows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
void NeonMeanScale(const float *din, float *dout, int size, const std::vector<float> mean, const std::vector<float> scale) { if (mean.size() != 3 || scale.size() != 3) { std::cerr << "[ПОМИЛКА] Розмір mean або scale має дорівнювати 3" << std::endl; exit(1); } float32x4_t vmean0 = vdupq_n_f32(mean[0]); float32x4_t vmean1 = vdupq_n_f32(mean[1]); float32x4_t vmean2 = vdupq_n_f32(mean[2]); float32x4_t vscale0 = vdupq_n_f32(scale[0]); float32x4_t vscale1 = vdupq_n_f32(scale[1]); float32x4_t vscale2 = vdupq_n_f32(scale[2]); float *dout_c0 = dout; float *dout_c1 = dout + size; float *dout_c2 = dout + size * 2; int i = 0; for (; i < size - 3; i += 4) { float32x4x3_t vin3 = vld3q_f32(din); float32x4_t vsub0 = vsubq_f32(vin3.val[0], vmean0); float32x4_t vsub1 = vsubq_f32(vin3.val[1], vmean1); float32x4_t vsub2 = vsubq_f32(vin3.val[2], vmean2); float32x4_t vs0 = vmulq_f32(vsub0, vscale0); float32x4_t vs1 = vmulq_f32(vsub1, vscale1); float32x4_t vs2 = vmulq_f32(vsub2, vscale2); vst1q_f32(dout_c0, vs0); vst1q_f32(dout_c1, vs1); vst1q_f32(dout_c2, vs2); din += 12; dout_c0 += 4; dout_c1 += 4; dout_c2 += 4; } for (; i < size; i++) { *(dout_c0++) = (*(din++) - mean[0]) * scale[0]; *(dout_c1++) = (*(din++) - mean[1]) * scale[1]; *(dout_c2++) = (*(din++) - mean[2]) * scale[2]; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Функція перетворена для платформи Windows x86/x64 void NeonMeanScale(const float *din, float *dout, int size, const std::vector<float> mean, const std::vector<float> scale) { if (mean.size() != 3 || scale.size() != 3) { std::cerr << "[ПОМИЛКА] Розмір mean або scale має дорівнювати 3" << std::endl; exit(1); } for (int i = 0; i < size; ++i) { dout[i] = (din[i] - mean[0]) * scale[0]; dout[size + i] = (din[size + i] - mean[1]) * scale[1]; dout[size * 2 + i] = (din[size * 2 + i] - mean[2]) * scale[2]; } } |
1 2 3 4 5 6 7 |
Ось як викликаються функції cv::Mat img_fp; // Завантаження зображення... auto *data0 = input_tensor0->mutable_data<float>(); std::vector<float> mean = {0.485f, 0.456f, 0.406f}; std::vector<float> scale = {1 / 0.229f, 1 / 0.224f, 1 / 0.225f}; const float *dimg = reinterpret_cast<const float *>(img_fp.data); NeonMeanScale(dimg, data0, img_fp.rows * img_fp.cols, mean, scale); |