首页 > 编程语言 >c++ 代码技巧

c++ 代码技巧

时间:2023-03-09 18:56:27浏览次数:41  
标签:10 return 技巧 ++ BM 代码 long c++ result

数学运算性能

大多数数据运算不存在性能问题,但是相对来说,整型的除法运算还是比较昂贵的。
参考下面的例子:

uint32_t BM_S1(uint64_t v) {
  uint32_t result = 0;
  do {
    ++result;
    v /= 10;
  } while (v);
  return result;
}

uint32_t BM_S2(uint64_t v) {
  uint32_t result = 1;
  for (;;) {
    if (v < 10) return result;
    if (v < 100) return result + 1;
    if (v < 1000) return result + 2;
    if (v < 10000) return result + 3;
    v /= 10000;
    result += 4;
  }
  return result;
}

uint32_t BM_S3(uint64_t v) {
  uint32_t result = 1;
  for (;;) {
    if (v < 10) return 1;
    if (v < 100) return 2;
    if (v < 1000) return 3;
    if (v < 1000000000000) {  // 10^12
      if (v < 100000000) {    // 10^7
        if (v < 1000000) {    // 10^6
          if (v < 10000) {
            return 4;
          }
          return 5 + (v >= 100000);  // 10^5
        }
        return 7 + (v >= 10000000);  // 10^7
      }
      if (v < 10000000000) {           // 10^10
        return 9 + (v >= 1000000000);  // 10^9
      }
      return 11 + (v >= 100000000000);  // 10^11
    }
    v /= 1000000000000;
    result += 12;
  }
  return result;
}

image
核心原因是因为 BM_S2 用比较和加法减少了除法运算,BM_S3通过搜索的方法进一步减少了除法操作。
运算速度可以参考下面:

* comparisons  (1 clock cycle)
* (u)int add, subtract, bitops, shift (1 clock cycle)
* floating point add, sub (3~6 clock cycle) 
* indexed array access (cache effects)
* (u)int32 mul  (3~4 clock cycle)
* Floating point mul (4~8 clock cycle)
* Float Point division, remainder (14~45 clock cycle)
* (u)int division, remainder (40~80 clock cycle)

除法比乘法要慢很多,所以有些除法运算可以利用乘法来加快:

double y, a1, a2, b1, b2;
y = a1/b1 + a2/b2;  // slow
double y, a1, a2, b1, b2;
y = (a1*b2 + a2*b1) / (b1*b2); // faster

cache line

目前的计算机系统,cache line 是 64 字节,基于cache line 可以做一些优化,从而减少内存读取次数。但是有些场景,cache line 反而会拖慢,例如下面的结构体:

struct S {
  long long a;
  long long b;
};

如果两个线程,一个写a,一个写b,这样会频发的触发内存和cache的交互。通过添加占位,让a和b不在一个cache line上,性能会更好。

struct S2 {
  long long a;
  long long nonp[8];  // 占位,a、b 加载到不同的缓存行
  long long b;
};

选择删除vector中的某些元素

auto cond = [](int x) { return (x & 1 == 1); };
vec3.erase(std::remove_if(vec3.begin(), vec3.end(), cond), vec3.end());

时间复杂度是 O(n)

bench mark

之前一直用 https://quick-bench.com/ 做小段代码性能测试,但是最近这个网站挂了,还是在本地跑 benchmark 靠谱。

安装bench mark

git clone https://github.com/google/benchmark.git
git clone https://github.com/google/googletest.git benchmark/googletest
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=RELEASE ../benchmark
make -j4
# 如果想全局安装就接着运行下面的命令
sudo make install

demo

测试代码

#include <chrono>
#include <iostream>
#include <thread>

#include <benchmark/benchmark.h>

struct S {
  long long a;
  long long b;
};

struct S2 {
  long long a;
  long long nonp[8];  // 占位,a、b 加载到不同的缓存行
  long long b;
};

void func1() {
  S s;
  std::thread t1([&]() {
    for (int i = 0; i < 100000; i++) {
      s.a++;
    }
  });
  std::thread t2([&]() {
    for (int i = 0; i < 100000; i++) {
      s.b++;
    }
  });
  t1.join();
  t2.join();
}

void func2() {
  S2 s;
  std::thread t1([&]() {
    for (int i = 0; i < 100000; i++) {
      s.a++;
    }
  });
  std::thread t2([&]() {
    for (int i = 0; i < 100000; i++) {
      s.b++;
    }
  });
  t1.join();
  t2.join();
}

static void BM_S(benchmark::State& state) {
  for (auto _ : state) {
    func1();
  }
}
BENCHMARK(BM_S);

static void BM_S2(benchmark::State& state) {
  for (auto _ : state) {
    func2();
  }
}
BENCHMARK(BM_S2);

BENCHMARK_MAIN();

编译(mac os)

clang++ -Wall -std=c++14 cache_line.cpp -I /usr/local/include -L /usr/local/lib -L /usr/lib -pthread -lbenchmark -o test

执行结果
image

标签:10,return,技巧,++,BM,代码,long,c++,result
From: https://www.cnblogs.com/xianzhedeyu/p/17183976.html

相关文章

  • C++常用遍历算法 for_each
    #include<iostream>#include<vector>#include<functional>#include<algorithm>usingnamespacestd;//遍历函数for_each//普通函数voidprint1(intval){......
  • c++之虚基类
    1.虚基类在多继承关系中,如果一个派生类的从两个父类那里继承过来,并且这两个父类又恰恰是从一个基类那里继承而来。那这样就麻烦了,因为你可能继承了两份一样的成员!这不仅多......
  • 斯坦福 UE4 C++ ActionRoguelike游戏实例教程 02.AI自定义任务和观察器中断
    斯坦福课程UE4C++ActionRoguelike游戏实例教程0.绪论概述本文章对应课程第十一章42节。这篇文章会进一步地为AI添加新功能,创建自定义任务,允许AI发射子弹,并且讲解观......
  • C++笔记--函数、预处理
    1函数1.1函数的介绍1.1.1函数的概述函数是c语言的功能单位。实现一个功能可以封装一个函数来实现。定义函数的时候一切以功能为目的,根据功能去定函数的参数和返回值......
  • 最终挂掉的代码
    [NOIP2005提高组]过河题目描述在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳......
  • ctfshow web入门 命令执行 特征及绕过技巧
    远程命令执行(RemoteCommandExecution,RCE)原理命令执行漏洞是指服务器没有对执行的命令进行过滤,用户可以随意执行系统命令,命令执行漏洞属于高危漏洞之一。危险函数......
  • 90后老板用低代码整顿文旅业,创2000万年收
    热爱旅游的92年成都小伙猴哥,大学毕业后开了一家旅行社,主要从事川藏、云南定制游服务。   从今年春节开始,国内各地旅游业开始复苏,向旅行社打电话咨询的人越来越多。......
  • c++11区域锁
    unique_lock方法说明详细说明unique_lock()noexcept;默认构造函数默认构造函数新创建的unique_lock对象不管理任何Mutex对象explicitunique_lock(mut......
  • EBS 开发技巧 常用代码
    Form开发技巧常用代码Form中的变量Form中用到的变量,总结如下:变量定义位置作用域,由低到高访问方法引用方式各层触发器中的变量该触发器FormPL/SQL变量......
  • C++ 三路快排 模板
    前言:今天被大作业的快速排序折磨的焦头烂额,原C++sort选手发现简洁的快排竟然如此难写(边界要注意的点好多qwq)。我原先的快排长这样:题解P1177【【模板】快速排序】......