首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++ 中文周刊 第89期

C++ 中文周刊 第89期

作者头像
王很水
发布2022-11-24 21:19:11
3910
发布2022-11-24 21:19:11
举报

C++ 中文周刊 第89期

资讯

标准委员会动态/ide/编译器信息放在这里

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-11-16 第176期

文章

使用target_clones能帮助生成平台兼容的SIMD代码,具体呢就是生成N份汇编。比如这种。https://godbolt.org/z/of5d6v

但问题在于,某些平台某些libc某些编译器可能不支持/支持程度不够,导致你用了这玩意但是实际上没生效,使用的时候需要注意

一个perf查性能的思路。当然循环里的if是比较不合时宜的,不利于编译器展开

循环访问大有学问,涉及到 循环的优化,上面也说了,循环里的条件判断非常不合理

constexpr auto tuple = [][[nodiscard]](auto... args) {
    return [=][[nodiscard]](auto fn)  { return fn(args...); };
};

constexpr auto apply(auto fn, auto t) { return t(fn); };

static_assert(0 == apply([](auto... args) { return sizeof...(args); }, tuple()));
static_assert(1 == apply([](auto... args) { return sizeof...(args); }, tuple(1)));
static_assert(2 == apply([](auto... args) { return sizeof...(args); }, tuple(1, 2)));

namespace detail {
template <std::size_t N, typename T> struct elem_by_index { T &ref; };
template <typename T> struct elem_by_type { T &ref; };
} // namespace detail

template <auto N> [[nodiscard]] constexpr auto get(auto t) {
    return t([]<typename... Ts>(Ts... elems) {
        return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
            struct all_elems : detail::elem_by_index<Is, Ts>... {};
            return []<typename U>(const detail::elem_by_index<N, U> &elem) {
                return elem.ref;
            }(all_elems{elems...});
        }(std::index_sequence_for<Ts...>{});
    });
}

template <class T> [[nodiscard]] constexpr auto get(auto t) {
    return t([]<typename... Ts>(Ts... elems) {
        struct all_elems : detail::elem_by_type<Ts>... {};
        return [](const detail::elem_by_type<T> &elem) {
            return elem.ref;
        }(all_elems{elems...});
    });
};

看不懂

改写这个

int f() {
    int* data = new int[2];
    data[0] = 1;
    data[1] = 2;
    int x = data[0];
    int y = data[1];
    int z = data[2];
    delete[] data;
    return x + y;
} 

用avx512 第一版

float dot512fma(float *x1, float *x2, size_t length) {
  // create a vector of 16 32-bit floats (zeroed)
  __m512 sum = _mm512_setzero_ps();
  for (size_t i = 0; i < length; i += 16) {
    // load 16 32-bit floats
    __m512 v1 = _mm512_loadu_ps(x1 + i);
    // load 16 32-bit floats

    __m512 v2 = _mm512_loadu_ps(x2 + i);
    // do sum[0] += v1[i]*v2[i] (fused multiply-add)
    sum = _mm512_fmadd_ps(v1, v2, sum);
  }
  // reduce: sums all elements
  return _mm512_reduce_add_ps(sum);
}

问题在于 i<length越界,如何解决 ?这就用标题讲的 mask load/store

float dot512fma(float *x1, float *x2, size_t length) {
  // create a vector of 16 32-bit floats (zeroed)
  __m512 sum = _mm512_setzero_ps();
  size_t i = 0;
  for (; i + 16 <= length; i+=16) {
    // load 16 32-bit floats
    __m512 v1 = _mm512_loadu_ps(x1 + i);
    // load 16 32-bit floats
    __m512 v2 = _mm512_loadu_ps(x2 + i);
    // do sum[0] += v1[i]*v2[i] (fused multiply-add)
    sum = _mm512_fmadd_ps(v1, v2, sum);
  }
  if  (i  < length) {
    // load 16 32-bit floats, load only the first length-i floats
    // other floats are automatically set to zero
    __m512 v1 = _mm512_maskz_loadu_ps((1<<(length-i))-1, x1 + i);
    // load 16 32-bit floats, load only the first length-i floats
    __m512 v2 = _mm512_maskz_loadu_ps((1<<(length-i))-1, x2 + i);
    // do sum[0] += v1[i]*v2[i] (fused multiply-add)
    sum = _mm512_fmadd_ps(v1, v2, sum);
  }
  // reduce: sums all elements
  return _mm512_reduce_add_ps(sum);
}

arm平台怎么做?

float dotsve(float *x1, float *x2, int64_t length) {
  int64_t i = 0;
  svfloat32_t sum = svdup_n_f32(0);
  while(i + svcntw() <= length) {
    svfloat32_t in1 = svld1_f32(svptrue_b32(), x1 + i);
    svfloat32_t in2 = svld1_f32(svptrue_b32(), x2 + i);
    sum = svmad_f32_m(svptrue_b32(), in1, in2, sum);
    i += svcntw();
  }
  svbool_t while_mask = svwhilelt_b32(i, length);
  do {
    svfloat32_t in1 = svld1_f32(while_mask, x1 + i);
    svfloat32_t in2 = svld1_f32(while_mask, x2 + i);
    sum = svmad_f32_m(svptrue_b32(), in1, in2, sum);
    i += svcntw();
    while_mask = svwhilelt_b32(i, length);
  } while (svptest_any(svptrue_b32(), while_mask));

  return svaddv_f32(svptrue_b32(),sum);
}

代码在这里,可以简单玩一下 https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/tree/master/2022/11/08

鼓励多用final。这个是常识了

代码重构。没啥说的

介绍 ODR相关的检测,很长

编译期的字符串,怎么编译期查长度?strlen不是constexpr,不行

#include <string>

constexpr std::size_t constexpr_strlen(const char* s)
{
    return std::char_traits<char>::length(s);
    // return std::string::traits_type::length(s);
}

constexpr std::size_t constexpr_wcslen(const wchar_t* s)
{
    return std::char_traits<wchar_t>::length(s);
    //  return std::wstring::traits_type::length(s);
}

void f() { E1 x = static_cast(2); // undefined behavior, 2 is outside the range of values }

``` 这种是UB,UBSan能抓到,也可以用 -fstrict-enums来抓

介绍了一些语言相关的优化/论文/点子,比如GC/JIT之类的,jdk/python相关的进展,感兴趣的可以看看

视频

这周没看。有啥推荐的也可以发一下。CPPCON 2022新出了俩协程教程,没看

开源项目需要人手

  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线

新项目介绍/版本更新

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C++ 中文周刊 第89期
    • 资讯
      • 文章
        • 视频
          • 开源项目需要人手
            • 新项目介绍/版本更新
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档