如何快速将6字节无符号整数复制到内存区域?

HEK*_*KTO 8 c c++ memory

我需要将一个6字节的整数值复制到一个内存区域,从它的开始和尽可能快的方式开始.如果硬件支持这样的操作,我想使用它(我现在在x64处理器上,编译器是GCC 4.6.3).

memset不适合作业,因为它只能复制字节.这std::fill也不好,因为我甚至无法定义迭代器,在内存区域中的6个字节宽度位置之间跳转.

所以,我想要一个功能:

void myMemset(void* ptr, uint64_t value, uint8_t width, size_t num)
Run Code Online (Sandbox Code Playgroud)

这看起来像memset,但有一个额外的参数width来定义如何多字节value复制.如果这样的东西可以用C++表达,那就更好了.

我已经知道了明显的myMemset实现,它将调用memcpy带有最后一个参数(要复制的字节)的in循环等于width.我也知道,我可以用大小6 * 8 = 48字节定义一个临时内存区域,用6字节整数填充它然后memcpy到目标区域.

我们可以做得更好吗?

chu*_*ica 6

沿东西@马克赎金的评论:

复制6个字节,然后复制6,12,24,48,96等.

void memcpy6(void *dest, const void *src, size_t n /* number of 6 byte blocks */) {
  if (n-- == 0) {
    return;
  }
  memcpy(dest, src, 6);
  size_t width = 1;
  while (n >= width) {
    memcpy(&((char *) dest)[width * 6], dest, width * 6);
    n -= width;
    width <<= 1; // double w
  }
  if (n > 0) {
    memcpy(&((char *) dest)[width * 6], dest, n * 6);
  }
}
Run Code Online (Sandbox Code Playgroud)

优化:规模nwidth6.

[编辑]
更正目的地@SchighSchagh已
添加演员表(char *)


chu*_*ica 1

一次写入 8 个字节。

在 64 位机器上,生成的代码当然可以很好地进行 8 字节写入操作。处理完一些设置问题后,在紧密循环中,每次写入大约 8 字节num。假设适用 - 请参阅代码。

// assume little endian
void myMemset(void* ptr, uint64_t value, uint8_t width, size_t num) {
  assert(width > 0 && width <= 8);

  uint64_t *ptr64 = (uint64_t *) ptr;
  // # to stop early to prevent writing past array end
  static const unsigned stop_early[8 + 1] = { 0, 8, 3, 2, 1, 1, 1, 1, 0 };
  size_t se = stop_early[width];
  if (num > se) {
    num -= se;

    // assume no bus-fault with 64-bit write @ `ptr64, ptr64+1, ... ptr64+7`
    while (num > 0) { // tight loop
      num--;
      *ptr64 = value;
      ptr64 = (uint64_t *) ((char *) ptr64 + width);
    }

    ptr = ptr64;
    num = se;
  }
  // Cope with last few writes
  while (num-- > 0) {
    memcpy(ptr, &value, width);
    ptr = (char *) ptr + width;
  }
}
Run Code Online (Sandbox Code Playgroud)

进一步的优化包括一次写入 2 个块width == 3 or 4、一次写入 4 个块width == 2以及一次写入 8 个块width == 1