@㝶芾厶眵攴䭡,回报率提高,游戏内灵敏度就需要降低,否则移动速度就会过快。
G304牛逼![]()
fps游戏鼠标回报率当然越高越好啊,影响真的很大
编译器认为 this 没被改,但 this->target 可能被改了。。
其实这句话没说错:
因此,每次修改 target,编译器认为 this 也可能随之变化,即 target[0] = t & 0x7; 可能改变了 this 指针。
因为
this
(也就是RDX寄存器的值)可能变了,所以才需要重新加载this->target
。那为什么不需要重新加载
this
呢?因为它就在寄存器,所以自然不需要重新加载,直接用就好了。
https://blog.csdn.net/xkdlzy/article/details/108873014
小于等于64位的整型或指针类型返回值由RAX传递。
浮点返回值由XMM0传递。
更大的返回值(比如结构体),由调用方在栈上分配空间,并有RCX持有该空间的指针并传递给被调用函数,因此整型参数使用的寄存器依次右移一格,实际只可以利用3个寄存器,其余参数入栈。函数调用结束后,RAX返回该空间的指针。但函数没有返回值(void),所以不清楚上面的案例中RCX用于什么,x64调用约定没有明说。
@无名啊,对了,VC++的__thiscall调用约定始终将this指针放在ecx寄存器。
https://learn.microsoft.com/zh-cn/cpp/cpp/thiscall?view=msvc-170
__thiscall 的调用约定用于 x86 体系结构上的 C++ 类成员函数。 它是成员函数使用的默认调用约定。
在 __thiscall 下,被调用方清理堆栈,自变量将从右到左推送到堆栈中。 指针 this 通过寄存器 ECX 传递,而不是在堆栈上传递。
@老虎会游泳,噢,是我想错了
编译器认为
this
没被改,但this->target
可能被改了。。x64 时,
this
作为第一个参数,存在 rdi 中?
@无名啊,
this
可能已经优化到了寄存器中。T::unpack3bit 每次移位之前都重新获取 target 变量的地址放到 rdi 中,
mov rdi, QWORD PTR [rdx]
,而 target 整个过程没有改变,这样做没有必要。这里是在读取
target
指针的值,mov rdi, QWORD PTR [rdx]
,是以rdx
寄存器的值为内存首地址,连续读取8字节到rdi
寄存器。因为
target
是struct T
的第一个成员,所以它的首地址就是this
。也就是说,this
在rdx
寄存器。所以问题是程序一直在从内存加载
this->target
,而非一直在从内存加载this
。
int a, b, c, d, e, f, g; int *h = &b;
而在这种情况下,可能是a、c、d、e、h在寄存器,b在内存,因为
&b
需要一个内存地址。指针h通常在寄存器,因为这样更快。至于a、c、d、e、f、g哪个在寄存器哪个在内存,取决于它们的使用情况。
@老虎会游泳,
this
符合【完全优化至寄存器的条件】吗?我记得是只读的啊。。那篇文章里,也没有要&this
。。
@无名啊,举个例子:
int a, b, c, d, e, f, g;
如果有5个空闲寄存器,那么a到e就只在寄存器,完全不在内存,f和g在内存,根据需要读取到寄存器。
既然可以完全优化至寄存器,自然不需要考虑缓存失效问题。
而指向缓冲区的局部指针变量恰好符合完全优化至寄存器的条件。
@无名啊,
this
是一个内存地址,既然是内存地址,所以当然在内存。编译器的问题只是在没有必要的情况下反复读取了它。而我说的寄存器变量,是完全不在内存,在且仅在寄存器的变量,这样的变量根本没有内存地址。
@老虎会游泳,我能看懂一点点汇编,你说的我能理解。(看过半本墨绿色的 x86 汇编书,但没咋写过,又都忘得差不多了。。
)
@无名啊,寄存器没有内存地址,所以任何有地址的内容必然在内存,但是在内存不意味着慢,因为它还可以同时存在于L3/L2/L1缓存中,而且也不必马上写回内存。
任何不需要有内存地址的内容,都可以放进寄存器,只要寄存器还没满。
内容在不在寄存器是静态分配的,编译的时候就决定了,查看汇编代码就能看出来。
如果寄存器还没满,并且内容不需要有内存地址,编译器没有理由不把它放进寄存器,除非专门指示它不进行此类优化(
-O0
或volatile
)。
@无名啊,以下是可能的分配:
char buf[16]; // 数组只能在内存,因为数组访问操作涉及取地址。内存中的数据会自动逐级缓存在L3/L2/L1 Cache,该操作由CPU自动完成。 char *read_next = buf; // 指针本身可以在寄存器,指向的内容当然不在寄存器,只可能在内存和缓存中 char *write_next = buf + 16; // 指针本身可以在寄存器,指向的内容当然不在寄存器,只可能在内存和缓存中
如果一个内容可以被指针指向,意味着它一定有一个内存地址,也就是说它一定在内存中,当然它也可以同时在L3/L2/L1 Cache中,但不会在寄存器中。在寄存器中的内容没有内存地址。
但是指针本身(也就是内存地址这个数值本身)可以在寄存器中。
@老虎会游泳,意思是,拿某个寄存器来存
read_next
,而不存入栈上了好像写入数组末尾之后,是未定义行为。这么说,编译器认为
read_next
未被修改也无不可。。哎,还是等写完之后,再加
restrict
试试吧。反正也不是啥速度极为严苛的场景,只是想顺便学学restrict
而已