Я пишу код для суперразрешения с помощью cpp, и в этом примере я использую libtorch и numcpp.
Мне нужно вычислить информацию о пикселях img после масштабирования (масштаб равен 2 в моем примере), который будет тратить время цикла new_img_width * new_img_height. Однако я также должен получить новую информацию из исходного img (то есть я добавляю внутренний цикл с old_img_width * old_img_height раз во внешнем цикле) и общее время циклов будет огромным (new_img_width * new_img_height * old_img_width * old_img_height), мне нужно провести некоторую оптимизацию циклов (внутренний цикл тратит всего 0,005 с), но все это время все еще долго, потому что внешние циклы огромны, как я могу оптимизировать свои код?
Дополнительная информация к коду:
1.merging_t — это класс, содержащий только некоторые скалярные данные
2.nc::NdArray — это numpy.ndarray для cpp
3.другие функции в кодах просто выполняют быстрые математические вычисления
в моем коде первой редакции я использую оператор перегрузки индекса torch::Tensor (т.е. оператор[]), изменяя данные Tensor напрямую, теперь я знаю, что это очень медленно, поэтому я использую исходный указатель для изменения данных и построения из них тензора во втором издании (это пример), правда в том, что общее время все еще очень велико, хотя я заменяю все места, где могу использовать исходный указатель.
Я пробовал omp.h, особого эффекта не дало.
может быть, cuda(GPU) — хорошее направление, но я AMD
Я пишу код для суперразрешения с помощью cpp, и в этом примере я использую libtorch и numcpp. Мне нужно вычислить информацию о пикселях img после масштабирования (масштаб равен 2 в моем примере), который будет тратить время цикла new_img_width * new_img_height. Однако я также должен получить новую информацию из исходного img (то есть я добавляю внутренний цикл с old_img_width * old_img_height раз во внешнем цикле) и общее время циклов будет огромным (new_img_width * new_img_height * old_img_width * old_img_height), мне нужно провести некоторую оптимизацию циклов (внутренний цикл тратит всего 0,005 с), но все это время все еще долго, потому что внешние циклы огромны, как я могу оптимизировать свои код? Дополнительная информация к коду: 1.merging_t — это класс, содержащий только некоторые скалярные данные 2.nc::NdArray — это numpy.ndarray для cpp 3.другие функции в кодах просто выполняют быстрые математические вычисления [code] void merge(nc::NdArray& comp_img, at::Tensor& alignments, at::Tensor& covs, nc::NdArray r, at::Tensor& num, at::Tensor& den, int options, params::merging_t& params) { float scale = params.scale; nc::NdArray CFA_pattern = params.exif.CFA_Pattern; bool bayer_mode = params.mode == "bayer"; bool iso_kernel = params.kernel == "iso"; int tile_size = params.tuning.tileSize; int input_size_y = comp_img.shape().rows, input_size_x =comp_img.shape().cols; int64_t align_y = alignments.sizes()[0], align_x = alignments.sizes()[1], align_c = alignments.sizes()[2]; int64_t num_y = num.sizes()[0], num_x = num.sizes()[1], num_c = num.sizes()[2]; int64_t den_y = den.sizes()[0], den_x = den.sizes()[1], den_c = den.sizes()[2]; int64_t covs_y = covs.sizes()[0], covs_x = covs.sizes()[1]; float* num_data = new float[num_y*num_x*num_c](); float* den_data = new float[den_y * den_x * den_c](); float* align_data = new float[align_y * align_x * align_c]; float* covs_data = new float[covs_y * covs_x * 2 * 2]; std::memcpy(covs_data, covs.data_ptr(), covs.numel() * sizeof(float)); std::memcpy(align_data, alignments.data_ptr(), sizeof(float) * alignments.numel()); //H W C for (int output_pixel_idy = 0; output_pixel_idy < num_y; ++output_pixel_idy) { for (int output_pixel_idx = 0; output_pixel_idx < num_x; ++output_pixel_idx) {
int center_x = std::round(patch_center_pos[1]); int center_y = std::round(patch_center_pos[0]); for (int i = -1; i < 2; ++i) { for (int j = -1; j < 2; ++j) { for (int pixel_idx = center_x + j; pixel_idx < input_size_x; ++pixel_idx) { for (int pixel_idy = center_y + i; pixel_idy < input_size_y; ++pixel_idy) { int channel = bayer_mode ? local_CFA(pixel_idy % 2, pixel_idx % 2) : 0; float c =comp_img(pixel_idy, pixel_idx); float dist_x = pixel_idx - patch_center_pos[1]; float dist_y = pixel_idy - patch_center_pos[0]; float y; if (iso_kernel) { y = max(0, 2 * (dist_x * dist_x + dist_y * dist_y)); } else { y = max(0, linalg::quad_mat_prod(cov_i, dist_x, dist_y)); }
float w = std::exp(-0.5 * y); val[channel] += c * w * local_r; acc[channel] += w * local_r; } } } } for (int chan = 0; chan < n_channels; ++chan) { num_data[output_pixel_idy * num_x * num_c + output_pixel_idx * num_c + chan] += val[chan]; den_data[output_pixel_idy * num_x * num_c + output_pixel_idx * num_c + chan] += acc[chan]; } } } num = torch::from_blob(num_data, { num_y,num_x,num_c }, c10::kFloat).clone(); den = torch::from_blob(den_data, { den_y,den_x,den_c }, c10::kFloat).clone(); delete[] num_data; delete[] den_data; delete[] covs_data; delete[] align_data; } } [/code] в моем коде первой редакции я использую оператор перегрузки индекса torch::Tensor (т.е. оператор[]), изменяя данные Tensor напрямую, теперь я знаю, что это очень медленно, поэтому я использую исходный указатель для изменения данных и построения из них тензора во втором издании (это пример), правда в том, что общее время все еще очень велико, хотя я заменяю все места, где могу использовать исходный указатель. Я пробовал omp.h, особого эффекта не дало. может быть, cuda(GPU) — хорошее направление, но я AMD