Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 优化内存_C++_Compiler Optimization - Fatal编程技术网

C++ 优化内存

C++ 优化内存,c++,compiler-optimization,C++,Compiler Optimization,为了避免违反严格的别名规则,我在代码中的几个地方引入了memcpy,希望它是不可操作的。下面的示例在gcc和clang上生成对memcpy(或等效)的调用。具体来说,fool总是这样做,而foo在gcc上做,但不在gcc上,而fool在clang上做,但不在gcc上。何时/如何对此进行优化 uint64_t bar(const uint16_t *buf) { uint64_t num[2]; memcpy(&num, buf, 16); return num[0] + nu

为了避免违反严格的别名规则,我在代码中的几个地方引入了
memcpy
,希望它是不可操作的。下面的示例在gcc和clang上生成对
memcpy
(或等效)的调用。具体来说,
fool
总是这样做,而
foo
在gcc上做,但不在gcc上,而
fool
在clang上做,但不在gcc上。何时/如何对此进行优化

uint64_t bar(const uint16_t *buf) {
  uint64_t num[2];
  memcpy(&num, buf, 16);
  return num[0] + num[1];
}

uint64_t foo(const uint16_t *buf) {
  uint64_t num[3];
  memcpy(&num, buf, sizeof(num));
  return num[0] + num[1];
}

template <int SZ>
uint64_t fool(const uint16_t *buf) {
  uint64_t num[SZ];
  memcpy(&num, buf, sizeof(num));
  uint64_t ret = 0;
  for (int i = 0; i < SZ; ++i)
    ret += num[i];
  return ret;
}

template uint64_t fool<2>(const uint16_t*);
template uint64_t fool<40>(const uint16_t*);
uint64\u t条(const uint16\u t*buf){
uint64_t num[2];
memcpy(&num,buf,16);
返回数值[0]+num[1];
}
uint64_t foo(常数uint16_t*buf){
uint64_t num[3];
memcpy(&num,buf,sizeof(num));
返回数值[0]+num[1];
}
模板
uint64傻瓜(常数uint16*buf){
uint64_t num[SZ];
memcpy(&num,buf,sizeof(num));
uint64_t ret=0;
对于(int i=0;i

我不能确切地告诉您为什么各个编译器没有按照您希望它们在特定情况下进行优化的方式来优化代码。我猜每个编译器要么就是无法跟踪memcpy在目标数组和源内存之间建立的关系(正如我们所看到的,至少在某些情况下,它们似乎能够识别这种关系),要么只是通过一些启发式方法告诉它们选择不使用它

无论如何,由于编译器的行为似乎不像我们希望的那样,当我们依赖它们跟踪整个数组时,我们可以尝试做的是,通过在每个元素的基础上执行memcpy,让编译器更清楚地看到它。这请注意,我必须在
bar
foo
中手动展开初始化,否则clang将再次进行复制


< >除了注意,在C++中,你应该使用<代码> STD::MycPy,<代码> STD::UTIN 64×T/<代码>等。因为标准头也将这些名字引入到全局命名空间中(虽然我不知道任何实现都没有这样做)。code>
既不使用clang也不使用gcc调用
memcpy
<代码>仅使用叮当声调用
memcpy
。如果你只为一个
uint64\u t
应用
memcpy
,一个接一个地(我的意思是,将
memcpy
放入for循环),你可以很容易地删除它。@geza他们产生了一个“等价物”(这是公认的不精确…)。也就是说,有一个对应的
mov
,这很可能意味着memcpy是内联的,而(不幸的)没有其他内容。因此,虽然没有对memcpy函数的实际调用,但仍在进行复制,而不是将给定内存片段简单地解释为目标类型的对象的预期效果。