how many times should i use "NV_CUDA_CHECK(cudaDeviceSynchronize());" in code "//resize input image to the size required by neural net
        cv::Mat image_resized(h_, w_, CV_8UC3, inputCpu_);
        if (up_crop_ != 0)
        {
            std::int16_t cropRows = image.rows - up_crop_;
            cv::Rect crop(0, up_crop_, image.cols, cropRows);
            cv::Mat img_crop = image(crop);
            cv::resize(img_crop, image_resized, cv::Size(w_, h_));
        }
        else
        {
            cv::resize(image, image_resized, cv::Size(w_, h_));
        }
        cudaStream_t stream; 
        NV_CUDA_CHECK(cudaStreamCreate(&(stream)));

        // Создание событий CUDA
        cudaEvent_t startEvent, stopEvent;
        NV_CUDA_CHECK(cudaEventCreate(&startEvent));
        NV_CUDA_CHECK(cudaEventCreate(&stopEvent));

        // Запись начала события перед копированием на GPU
        NV_CUDA_CHECK(cudaEventRecord(startEvent, 0));

        //transfer the image to GPU
        NV_CUDA_CHECK(cudaMemcpyAsync(inputGpu_, inputCpu_, h_ * w_ * 3 * sizeof(unsigned char), cudaMemcpyHostToDevice, stream));
        NV_CUDA_CHECK(cudaStreamSynchronize(stream));
        NV_CUDA_CHECK(cudaDeviceSynchronize());

        // Запись окончания события после копирования на GPU
        NV_CUDA_CHECK(cudaEventRecord(stopEvent, 0));
        NV_CUDA_CHECK(cudaEventSynchronize(stopEvent));

        // Получение времени выполнения и вычисление пропускной способности
        float time;
        NV_CUDA_CHECK(cudaEventElapsedTime(&time, startEvent, stopEvent));
        size_t bytes = h_ * w_ * 3 * sizeof(unsigned char);
        float bandwidth = bytes * 1e-6 / time;
        printf("Host to Device bandwidth (GB/s): %f\n", bandwidth);

        //normalize image and reshape it such that it has channels-first format (required by neural net)
        NV_CUDA_CHECK(preprocessOnGpuWrapper(inputGpu_, inputCfGpu_, h_, w_, coef_, mean_[0], mean_[1], mean_[2], std_[0], std_[1], std_[2]));

        //inference
        buffers_[0] = inputCfGpu_;
        buffers_[1] = outputRawGpu_;

        for (int32_t i = 0, e = engine_->getNbIOTensors(); i < e; i++)
        {
            auto const name = engine_->getIOTensorName(i);
            context_->setTensorAddress(name, (void **)buffers_[i]);
        }

        // Asynchronously enqueue the inference work
        if (!context_->enqueueV3(stream))
        {
            std::cerr << "Error async enqueue inference ." << std::endl;
        }

        //compute segmentation masks from raw neural net ouput
        NV_CUDA_CHECK(computeOutputOnGpuWrapper(outputRawGpu_, outputMaskGpu_, h_, w_, numClasses_, threshold_));

        // Запись начала события перед копированием с GPU на хост
        NV_CUDA_CHECK(cudaEventRecord(startEvent, 0));

        //transfer result from GPU to the host
        NV_CUDA_CHECK(cudaMemcpyAsync(outputMaskCpu_, outputMaskGpu_, h_ * w_ * sizeof(unsigned char), cudaMemcpyDeviceToHost, stream)); // V1-2, 5
        NV_CUDA_CHECK(cudaStreamSynchronize(stream));
        
        // Запись окончания события после копирования с GPU на хост
        NV_CUDA_CHECK(cudaEventRecord(stopEvent, 0));
        NV_CUDA_CHECK(cudaEventSynchronize(stopEvent));
        NV_CUDA_CHECK(cudaEventElapsedTime(&time, startEvent, stopEvent));
        bytes = h_ * w_ * sizeof(unsigned char);
        bandwidth = bytes * 1e-6 / time;
        printf("Device to Host bandwidth (GB/s): %f\n", bandwidth);

        // Уничтожение событий
        NV_CUDA_CHECK(cudaEventDestroy(startEvent));
        NV_CUDA_CHECK(cudaEventDestroy(stopEvent));

        // Wait for the work in the stream to complete.
        // Release stream.
        NV_CUDA_CHECK(cudaStreamDestroy(stream));"