Skip to content

Latest commit

 

History

History
259 lines (225 loc) · 8.48 KB

0.手写循环队列指针取缔双buffer拷贝.md

File metadata and controls

259 lines (225 loc) · 8.48 KB

image

#include <Eigen/Core>
#include <Eigen/Eigen>
#include <chrono>
#include <iomanip>  // For setw
#include <iostream>
#include <typeinfo>
#include <unordered_set>
#include <vector>

#include "Eigen/Dense"
using namespace std;

#define START_LOG_TIME()                                  \
  std::chrono::high_resolution_clock::time_point t1 =     \
      std::chrono::high_resolution_clock::now();          \
  std::chrono::high_resolution_clock::time_point t2 = t1; \
  std::chrono::duration<double> time_used =               \
      std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);
#define PRINT_COST_TIME(name)                                             \
  t2 = std::chrono::high_resolution_clock::now();                         \
  time_used =                                                             \
      std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1); \
  std::cout << std::fixed << name                                         \
            << " Time cost: " << (time_used.count() * 1000) << " ms."     \
            << std::endl;                                                 \
  t1 = t2;

template <typename T>
class DataManagerOrigin {
 public:
  typedef std::vector<T> DataType;
  typedef typename std::vector<T>::iterator DataTypeIterator;

  DataManagerOrigin() = default;

  ~DataManagerOrigin() = default;

  bool Init(const Eigen::Vector2i& size) {
    size_ = size;
    buffer_[0].resize(size_(0) * size_(1));
    buffer_[1].resize(size_(0) * size_(1));
    data_ = &buffer_[0];
    return true;
  }

  size_t size() const { return data_->size(); }

  T& at(size_t idx) { return data_->at(idx); }

  void Shift(const Eigen::Vector2i& offset) {
    const int32_t half_rows = static_cast<int32_t>(std::floor(size_(0) / 2));
    const int32_t half_cols = static_cast<int32_t>(std::floor(size_(1) / 2));
    // LOG_INFO << "wyh offset " << offset << " half_rows " << half_rows
    //          << " half_cols " << half_cols << " size_ " << size_;
    // offset 0 1 half_rows 150 half_cols 150 size_ 300 300
    if (abs(offset(0)) > half_rows || abs(offset(1)) > half_cols) {
      memset(data_->data(), 0, sizeof(T) * data_->size());
    }
    if (abs(offset(0)) >= 1 || abs(offset(1)) >= 1) {
      DataType* src = nullptr;
      DataType* dst = nullptr;
      if (data_ == &buffer_[0]) {
        src = &buffer_[0];
        dst = &buffer_[1];
      } else {
        src = &buffer_[1];
        dst = &buffer_[0];
      }
      data_ = dst;
      memset(data_->data(), 0, sizeof(T) * data_->size());
      Eigen::Vector2i start_src;
      Eigen::Vector2i end_src;
      start_src(0) = std::max(0, offset(0));                          // 1
      start_src(1) = std::max(0, offset(1));                          // 1
      end_src(0) = std::min(size_(0) - 1, size_(0) - 1 + offset(0));  // 2
      end_src(1) = std::min(size_(1) - 1, size_(1) - 1 + offset(1));  // 2
      if (start_src(0) > end_src(0) || start_src(1) > end_src(1)) {
        return;
      }
      const Eigen::Vector2i start_dst = start_src - offset;  // 0
      const Eigen::Vector2i end_dst = end_src - offset;      // 1
      const int col_length = end_src(1) - start_src(1) + 1;  // 2
      // LOG_INFO << "wyh start_src " << start_src << " end_src " << end_src
      //          << " start_dst " << start_dst << " end_dst " << end_dst
      //          << " col_length " << col_length << " offset " << offset
      //          << " size_ " << size_;
      // wyh start_src 0 1 end_src 299 299 start_dst 0 0 end_dst 299 298
      // col_length 299 offset 0 1 size_ 300 300
      for (int row = start_dst(0); row <= end_dst(0); ++row) {  // 0-1
        const int src_start_idx =
            (row + offset(0)) * size_(1) + start_src(1);          // 4 7
        const int dst_start_idx = row * size_(1) + start_dst(1);  // 0 3
        memcpy(&(dst->at(dst_start_idx)), &(src->at(src_start_idx)),
               sizeof(T) * col_length);
      }
    }
  }

  void Show(string str) {
    cout << str << "\n";
    for (int i = 0; i < size_(0); i++) {
      for (int j = size_(0) * i; j < size_(0) * i + size_(1); j++) {
        cout << setw(3) << data_->at(j) << " ";
      }
      cout << endl;
    }
  }

  void enqueue(const T& item) { data_->at(size_1d_++) = item; }

 private:
  DataType buffer_[2];
  DataType* data_ = nullptr;
  Eigen::Vector2i size_ = Eigen::Vector2i::Zero();
  int size_1d_ = 0;
};  // class DataManagerOrigin

template <typename T>
class DataManagerOpt {
 public:
  typedef std::vector<T> DataType;
  typedef typename std::vector<T>::iterator DataTypeIterator;

  DataManagerOpt() = default;

  ~DataManagerOpt() = default;

  bool Init(const Eigen::Vector2i& size) {
    size_ = size;
    buffer_.resize(size_(0) * size_(1));
    data_ = &buffer_;
    return true;
  }

  size_t size() const { return data_->size(); }

  T& at(size_t idx) { return data_->at((front_ + (int)idx) % data_->size()); }

  void Shift(const Eigen::Vector2i& offset) {
    const int32_t half_rows = static_cast<int32_t>(std::floor(size_(0) / 2));
    const int32_t half_cols = static_cast<int32_t>(std::floor(size_(1) / 2));
    // LOG_INFO << "wyh offset " << offset << " half_rows " << half_rows
    //          << " half_cols " << half_cols << " size_ " << size_;
    // offset 0 1 half_rows 150 half_cols 150 size_ 300 300
    if (abs(offset(0)) > half_rows || abs(offset(1)) > half_cols) {
      memset(data_->data(), 0, sizeof(T) * data_->size());
      return;
    }
    if (abs(offset(0)) >= 1 || abs(offset(1)) >= 1) {
      int new_front = front_ + offset(0) * size_(1) + offset(1);
      new_front = new_front >= 0 ? new_front : data_->size() - abs(new_front);
      front_ = new_front % data_->size();
      Eigen::Vector2i move_len;
      move_len(0) = size_(0) - abs(offset(0));
      move_len(1) = size_(1) - abs(offset(1));
      // cout << "move_len:\n" << move_len << endl;

      int protect_row_start = offset(0) > 0 ? 0 : abs(offset(0));
      int protect_row_stop = offset(0) > 0 ? move_len(0) - 1 : size_(0) - 1;
      int protect_col_start = offset(1) > 0 ? 0 : abs(offset(1));
      int protect_col_stop = offset(1) > 0 ? move_len(1) - 1 : size_(1) - 1;

      // cout << "protect_row_start " << protect_row_start << " protect_row_stop
      // "
      //      << protect_row_stop << " protect_col_start " << protect_col_start
      //      << " protect_col_stop " << protect_col_stop << endl;

      for (int i = 0; i < size_(0); i++) {
        for (int j = size_(0) * i; j < size_(0) * i + size_(1); j++) {
          int row = i;
          int col = j - (size_(0) * i);
          if (protect_row_start <= row && row <= protect_row_stop &&
              protect_col_start <= col && col <= protect_col_stop) {
            continue;
          }
          at(j) = 0;
        }
      }
    }
  }

  void Show(string str) {
    cout << str << "\n";
    for (int i = 0; i < size_(0); i++) {
      for (int j = size_(0) * i; j < size_(0) * i + size_(1); j++) {
        cout << setw(3) << at(j) << " ";
      }
      cout << endl;
    }
  }

  void enqueue(const T& item) {
    if (size_1d_ < data_->size()) {
      size_1d_++;
      data_->at((front_ + size_1d_ - 1) % data_->size()) = item;
    }
  }

 private:
  DataType buffer_;
  DataType* data_ = nullptr;
  Eigen::Vector2i size_ = Eigen::Vector2i::Zero();
  int front_ = 0;
  int size_1d_ = 0;
};  // class DataManagerOpt

int main() {
  const int kShiftTimes = 1;
  // const int kShiftTimes = 2;
  // const int kShiftTimes = 3;

  // Eigen::Vector2i size(5, 5);
  Eigen::Vector2i size(15, 15);
  // Eigen::Vector2i offset(2, 2);
  Eigen::Vector2i offset(1, -2);

  {
    DataManagerOrigin<int> layer_content;
    layer_content.Init(size);

    for (int i = 0; i < size(0) * size(1); ++i) {
      layer_content.enqueue(i + 1);
    }
    layer_content.Show("DataManagerOrigin Data:");

    {
      START_LOG_TIME()
      for (int i = 0; i < kShiftTimes; i++) {
        layer_content.Shift(offset);
        layer_content.Show("DataManagerOrigin Shift:");
      }
      PRINT_COST_TIME("DataManagerOrigin");
    }
  }
  {
    DataManagerOpt<int> layer_content;
    layer_content.Init(size);

    for (int i = 0; i < size(0) * size(1); ++i) {
      layer_content.enqueue(i + 1);
    }
    layer_content.Show("DataManagerOpt Data:");

    {
      START_LOG_TIME()
      for (int i = 0; i < kShiftTimes; i++) {
        layer_content.Shift(offset);
        layer_content.Show("DataManagerOpt Shift:");
      }
      PRINT_COST_TIME("DataManagerOpt");
    }
  }
  return 0;
}