我想检查boost::variant在我的代码中应用的程序集输出,以便查看哪些中间调用被优化掉了.
当我编译以下示例(使用GCC 5.3 g++ -O3 -std=c++14 -S)时,似乎编译器优化了所有内容并直接返回100:
(...)
main:
.LFB9320:
.cfi_startproc
movl $100, %eax
ret
.cfi_endproc
(...)
Run Code Online (Sandbox Code Playgroud)
#include <boost/variant.hpp>
struct Foo
{
int get() { return 100; }
};
struct Bar
{
int get() { return 999; }
};
using Variant = boost::variant<Foo, Bar>;
int run(Variant v)
{
return boost::apply_visitor([](auto& x){return x.get();}, v);
}
int main()
{
Foo f;
return run(f);
}
Run Code Online (Sandbox Code Playgroud)
但是,完整的程序集输出包含的内容远远超过上面的摘录,对我而言,它看起来永远不会被调用.有没有办法告诉GCC/clang删除所有"噪音"并输出程序运行时实际调用的内容?
完整装配输出:
.file "main1.cpp"
.section .rodata.str1.8,"aMS",@progbits,1
.align 8
.LC0:
.string "/opt/boost/include/boost/variant/detail/forced_return.hpp"
.section .rodata.str1.1,"aMS",@progbits,1
.LC1: …Run Code Online (Sandbox Code Playgroud) 有一个现有的问题“3 个长整数的平均值”,它特别关注三个有符号整数的平均值的有效计算。
然而,无符号整数的使用允许额外的优化不适用于上一个问题中涵盖的场景。这个问题是关于三个无符号整数的平均值的有效计算,其中平均值向零舍入,即在数学术语中我想计算?(a + b + c) / 3 ?。
计算此平均值的一种直接方法是
avg = a / 3 + b / 3 + c / 3 + (a % 3 + b % 3 + c % 3) / 3;
Run Code Online (Sandbox Code Playgroud)
首先,现代优化编译器会将除法转换为具有倒数加移位的乘法,并将模运算转换为反向乘法和减法,其中反向乘法可能使用许多体系结构上可用的scale_add习语,例如leax86_64的,add用lsl #n在ARM,iscadd在NVIDIA GPU。
在尝试以适用于许多常见平台的通用方式优化上述内容时,我观察到整数运算的成本通常在逻辑关系中?(添加|子)?转移?规模_添加?MUL。这里的成本是指所有延迟、吞吐量限制和功耗。当处理的整数类型比本地寄存器宽度更宽时,例如在uint64_t32 位处理器上处理数据时,任何此类差异都会变得更加明显。
因此,我的优化策略是尽量减少指令数量,并在可能的情况下用“廉价”操作替换“昂贵”操作,同时不增加寄存器压力并为宽无序处理器保留可利用的并行性。
第一个观察结果是,我们可以通过首先应用产生和值和进位值的 CSA(进位保存加法器)将三个操作数的和减少为两个操作数的和,其中进位值的权重是和的两倍价值。在大多数处理器上,基于软件的 CSA 的成本是五个逻辑s。一些处理器,如 …
c algorithm bit-manipulation micro-optimization extended-precision
在Chandler Carruth的CppCon 2015演讲中,他介绍了两种神奇的功能,可以在没有任何额外性能损失的情况下击败优化器.
作为参考,这里是函数(使用GNU样式的内联汇编):
void escape(void* p)
{
asm volatile("" : : "g"(p) : "memory");
}
void clobber()
{
asm volatile("" : : : "memory");
}
Run Code Online (Sandbox Code Playgroud)
它适用于任何支持GNU样式内联汇编的编译器(GCC,Clang,Intel编译器,可能还有其他编译器).但是,他提到它在MSVC中不起作用.
检查Google Benchmark的实现,似乎他们使用重新解释转换为a volatile const char&并将其传递给隐藏在非gcc/clang编译器上的不同翻译单元中的函数.
template <class Tp>
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
}
// some other translation unit
void UseCharPointer(char const volatile*) {}
Run Code Online (Sandbox Code Playgroud)
但是,我对此有两个顾虑:
MSVC中是否有与GNU样式的汇编函数相同的低级别?或者这是MSVC上最好的?
我正在阅读预防编译器优化,同时描述Chandler Carruths 如何clobber()和escape()来自 CppCon 2015:Chandler Carruth"调优C++:基准测试,CPU和编译器!哦我的!".影响编译器.
从阅读那里,我假设如果我有一个输入约束,如"g"(val),那么编译器将无法优化val.但是在g()下面,没有生成代码.为什么?
如何doNotOptimize()重写以确保生成代码g()?
template <typename T>
void doNotOptimize(T const& val) {
asm volatile("" : : "g"(val) : "memory");
}
void f() {
char x = 1;
doNotOptimize(&x); // x is NOT optimized away
}
void g() {
char x = 1;
doNotOptimize(x); // x is optimized away
}
Run Code Online (Sandbox Code Playgroud)
c++ assembly inline-assembly performance-testing compiler-optimization
操作系统:Linux(Debian 10)
CC:GCC 8.3
CPU:i7-5775C
在GCC中有一个unsigned __int128/ __int128,但是有什么办法在GCC中有一个uint256_t/ int256_t?
我读过一篇__m256i似乎来自英特尔的文章。我可以包含任何标头来获取它吗?
它像假设一样有用unsigned __int256吗?我的意思是,如果您可以为其分配/比较,比较,按位运算等。
它的等效符号是什么(如果有)?
编辑1:
我做到了:
#include <immintrin.h>
typedef __m256i uint256_t;
Run Code Online (Sandbox Code Playgroud)
并编译。如果可以进行一些操作,请在此处进行更新。
编辑2:
发现问题:
uint256_t m;
ptrdiff_t l = 5;
m = ~((uint256_t)1 << l);
Run Code Online (Sandbox Code Playgroud)
输出:
error: can’t convert a value of type ‘int’ to vector type ‘__vector(4) long long int’ which has different size
m = ~((uint256_t)1 << l);
Run Code Online (Sandbox Code Playgroud) 我创建了一个这样的结构:
struct Options {
double bindableKeys = 567;
double graphicLocation = 150;
double textures = 300;
};
Options options;
Run Code Online (Sandbox Code Playgroud)
在此声明之后,在另一个进程中,我打开包含该结构的进程并使用结构的双精度搜索字节数组,但未找到任何内容。
要获得结果,我需要std::cout << options.bindableKeys;在声明之后添加类似的内容。然后我从我的模式搜索中得到结果。为什么会有这样的行为?有什么解决办法吗?
最小可重现示例:
struct Options {
double bindableKeys = 567;
double graphicLocation = 150;
double textures = 300;
};
Options options;
while(true) {
double val = options.bindableKeys;
if(val > 10)
std::cout << "test" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
您可以使用 CheatEngine 或其他模式查找器搜索数组