我对手册页中的措辞感到困惑arch_prctl(2).具体来说,它指出:
64位段基的上下文切换相当昂贵. 通过在内核2.5或更高版本中使用modify_ldt(2)或使用set_thread_area(2)系统调用设置LDT,使用段选择器设置32位基址可能是更快的替代方法.只有当您想要设置大于4GB的基数时,才需要arch_prctl().可以使用带有MAP_32BIT标志的mmap(2)来分配前2GB地址空间中的内存.
这是否意味着使用此系统调用的进程的上下文切换将受到性能损失或具有哪些确切含义?
查看Linux内核的源代码后,似乎对于<4 GiB的地址使用LDT,而> 4 GiB地址使用特定于模型的寄存器.
case ARCH_SET_FS:
/* handle small bases via the GDT because that's faster to
switch. */
if (addr <= 0xffffffff) {
set_32bit_tls(task, FS_TLS, addr);
if (doit) {
load_TLS(&task->thread, cpu);
loadsegment(fs, FS_TLS_SEL);
}
task->thread.fsindex = FS_TLS_SEL;
task->thread.fs = 0;
} else {
task->thread.fsindex = 0;
task->thread.fs = addr;
if (doit) {
/* set the selector to 0 to not confuse
__switch_to */
loadsegment(fs, 0);
ret = wrmsrl_safe(MSR_FS_BASE, addr);
} …Run Code Online (Sandbox Code Playgroud) 在下面的C++源代码的汇编中.为什么RAX被推入堆栈?
正如我从ABI理解的那样,RAX可以包含来自调用函数的任何内容.但是我们将它保存在这里,然后将堆栈移回8个字节.所以堆栈上的RAX,我认为只与std::__throw_bad_function_call()操作相关......?
代码:-
#include <functional>
void f(std::function<void()> a)
{
a();
}
Run Code Online (Sandbox Code Playgroud)
gcc.godbolt.org使用Clang 3.7.1 -O3 输出:
f(std::function<void ()>): # @f(std::function<void ()>)
push rax
cmp qword ptr [rdi + 16], 0
je .LBB0_1
add rsp, 8
jmp qword ptr [rdi + 24] # TAILCALL
.LBB0_1:
call std::__throw_bad_function_call()
Run Code Online (Sandbox Code Playgroud)
我确定原因很明显,但我很难弄清楚.
这是一个没有std::function<void()>包装器的尾部调用,用于比较:
void g(void(*a)())
{
a();
}
Run Code Online (Sandbox Code Playgroud)
琐碎的:
g(void (*)()): # @g(void (*)())
jmp rdi # TAILCALL
Run Code Online (Sandbox Code Playgroud) 在我的程序中的某个时刻,我计算整数除数d.从那时起d,这将是不变的.
稍后在代码中我将除以它d几次 - 执行整数除法,因为值d不是编译时已知常量.
鉴于与其他类型的整数运算相比,整数除法是一个相对较慢的过程,我想优化它.我可以存储一些替代格式d,以便分割过程执行得更快吗?也许是某种形式的倒数?
我不需要d其他任何东西的价值.
值d是任何64位整数,但通常很适合32位.
我最近从Vista/32升级到Win7/64.在我的旧机器上,一切正常.
不幸的是,在我的新机器上,NUnit不会加载我的单元测试,错误消息"System.IO.FileNotFoundException:无法加载文件或程序集'UnitTest'或其依赖项之一.系统无法找到指定的文件".(实际上,我必须完成我所有解决方案的项目,并将它们设置为32位才能实现这一目标.)
所以我加载了Dependency Walker,它告诉我我错过了IESHIMS.DLL.我在我的机器上发现了两个,所以我从Internet Explorer目录中复制了32位版本,DW停止抱怨该文件.
但是,它也缺少GPSVC.DLL.我在C:\ Windows\System32中只发现了一个这样的副本,但当我将其复制到我的单元测试目录中时,DW抱怨它是64位,而NUnit仍然无法运行.它现在还将SYSNTFY.DLL添加到缺少的列表中.我只有其中一个,那也是64位.NUnit仍然报告错误.
那么我应该废弃这个64位操作系统并回到原来的32位,还是我错过了一些明显的东西?
我正在编写需要快速乘以大数的数学代码.它分解为整数数组与单个整数的乘法.在C++中,这看起来像这样(在unsigned上):
void muladd(unsigned* r, const unsigned* a, unsigned len, unsigned b) {
unsigned __int64 of = 0; // overflow
unsigned i = 0; // loop variable
while (i < len) {
of += (unsigned __int64)a[i] * b + r[i];
r[i] = (unsigned)of;
of >>= 32;
++i;
}
r[i] = (unsigned)of; // save overflow
}
Run Code Online (Sandbox Code Playgroud)
我手动展开了这个循环,将其转换为64位并处理.asm编译器输出以进一步优化它.主.asm循环现在看起来像这样:
mov rax, rdi ; rdi = b
mul QWORD PTR [rbx+r10*8-64] ; rdx:rax = a[i] * b; r10 = i
mov rsi, QWORD PTR [r14+r10*8-64] …Run Code Online (Sandbox Code Playgroud) 假设我在Linux中有一个使用共享库(.so文件)的应用程序.我的问题是这些库中的代码是否会在与主应用程序相同的堆中分配内存,还是使用自己的堆?
例如,.so文件调用中的某些函数malloc是否会使用与应用程序相同的堆管理器或另一个?此外,那些共享内存中的全局数据如何呢?它在哪里?我知道它的应用程序位于bss和数据段中,但不知道它们对于那些共享对象文件的位置.
在标准库(glibc)中,我看到使用前导双下划线定义的函数,例如__mmapin sys/mman.h.什么目的?我们怎样才能调用一个mmap似乎没有在任何地方声明的函数.我的意思是我们包括sys/mman.h,但sys/mman.h没有声明mmap,它只声明__mmap.
我最近发现使用placement new比执行16个赋值更快:
考虑以下代码段(c ++ 11):
class Matrix
{
public:
double data[16];
Matrix() : data{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }
{
};
void Identity1()
{
new (this) Matrix();
};
void Identity2()
{
data[0] = 1.0; data[1] = 0.0; data[2] = 0.0; data[3] = 0.0;
data[4] = 0.0; data[5] = 1.0; data[6] = 0.0; data[7] = 0.0;
data[8] = 0.0; data[9] = 0.0; data[10] = 1.0; data[11] = 0.0;
data[12] …Run Code Online (Sandbox Code Playgroud) 64位Linux默认使用小内存模型,它将所有代码和静态数据置于2GB地址限制之下.这可确保您可以使用32位绝对地址.较旧版本的gcc使用静态数组的32位绝对地址,以便为相对地址计算保存额外的指令.但是,这不再有效.如果我尝试在汇编中创建一个32位的绝对地址,我会收到链接器错误:"在创建共享对象时,不能使用".data"重定位R_X86_64_32S;使用-fPIC重新编译".当然,此错误消息具有误导性,因为我没有创建共享对象,-fPIC也没有帮助.到目前为止我发现的是:gcc版本4.8.5对静态数组使用32位绝对地址,gcc版本6.3.0不使用.版本5可能也没有.binutils 2.24中的链接器允许32位绝对地址,而2.28则不允许.
这种变化的后果是必须重新编译旧库并破坏传统汇编代码.
现在我想问一下:这个改变是什么时候做的?它在某处记录了吗?是否有一个链接器选项,使其接受32位绝对地址?
x86-64 ×10
gcc ×4
linux ×4
assembly ×3
c ×3
c++ ×3
performance ×3
optimization ×2
x86 ×2
.net ×1
32bit-64bit ×1
abi ×1
c++11 ×1
dependencies ×1
dll ×1
glibc ×1
gmp ×1
intel ×1
relocation ×1