Tag: x86

汇编代码fsqrt和fmul指令

我正在尝试使用汇编代码在此函数中计算1.34 * sqrt(lght),但我收到的错误如下: ‘_asm’未声明(在此函数中首次使用)每个未声明的标识符仅针对预期的’;’中出现的每个函数报告一次 在'{‘之前 我一直在研究如何解决这个问题,但找不到太多的信息。 有人可以建议一种让这个工作的方法吗? 我的代码是: double hullSpeed(double lgth) { _asm { global _start fld lght; //load lght fld st(0); //duplicate lght on Top of stack fsqrt; square root of lght fld st(0); //load square result on top of stack fld 1.34; //load 1.34 on top of stack fld st(i); duplicate 1.34 on […]

在x86机器上移位超过32位的uint64_t整数未定义的行为?

学习困难的方法,我试图在x86机器上留下很long long和uint64_t到超过32位的结果为0 。 我依稀记得曾经读过某个地方,而不是32位机器移位操作符只能在前32位工作但不能重新收集源。 我想知道是否在x86机器上移动超过32位的uint64_t整数是未定义的行为?

检查是否设置了进位标志

使用内联汇编程序[gcc,intel,c],如何在操作后检查进位标志是否设置?

在x86中有加速SHA(SHA1 / 2/256/512)编码的任何指令吗?

例如,在x86中是指令集到硬件加速AES 。 但是在x86中是否存在加速SHA(SHA1 / 2/256/512)编码的任何指令,以及在x86上编码SHA的紧固库是什么?

如何让GCC为没有内置的大端存储生成bswap指令?

我正在研究一个以大端格式将64位值存储到内存中的函数。 我希望我能编写可在小端和大端平台上运行的可移植C99代码,并让现代x86编译器自动生成bswap指令而不需要任何内置函数或内在函数 。 所以我开始使用以下function: #include void encode_bigend_u64(uint64_t value, void *vdest) { uint64_t bigend; uint8_t *bytes = (uint8_t*)&bigend; bytes[0] = value >> 56; bytes[1] = value >> 48; bytes[2] = value >> 40; bytes[3] = value >> 32; bytes[4] = value >> 24; bytes[5] = value >> 16; bytes[6] = value >> 8; bytes[7] = value; […]

L1内存带宽:使用相差4096 + 64字节的地址,效率下降50%

我想用英特尔处理器实现以下操作的最大带宽。 for(int i=0; i<n; i++) z[i] = x[i] + y[i]; //n=2048 其中x,y和z是浮点数组。 我在Haswell,Ivy Bridge和Westmere系统上这样做。 我最初分配了这样的内存 char *a = (char*)_mm_malloc(sizeof(float)*n, 64); char *b = (char*)_mm_malloc(sizeof(float)*n, 64); char *c = (char*)_mm_malloc(sizeof(float)*n, 64); float *x = (float*)a; float *y = (float*)b; float *z = (float*)c; 当我这样做时,我获得了每个系统预期的峰值带宽的大约50%。 峰值计算为frequency * average bytes/clock_cycle 。 每个系统的平均字节/时钟周期为: Core2: two 16 byte reads one […]

有效地将无符号值除以2的幂,四舍五入

我想用2的任意幂实现无符号整数除法 ,有效地向上舍入 。 所以我想要的是数学上的ceiling(p/q) 0 。 在C中,不利用q的受限域的strawman实现可能类似于以下函数1 : /** q must be a power of 2, although this version works for any q */ uint64_t divide(uint64_t p, uint64_t q) { uint64_t res = p / q; return p % q == 0 ? res : res + 1; } …当然,我实际上并不想在机器级别使用除法或mod,因为即使在现代硬件上也需要很多周期。 我正在寻找使用轮class和/或其他一些廉价操作的力量减少 – 利用q是2的幂的事实。 你可以假设我们有一个有效的lg(unsigned int […]

x86上交换与比较和交换锁的相对性能

两种常见的锁定习语是: if (!atomic_swap(lockaddr, 1)) /* got the lock */ 和: if (!atomic_compare_and_swap(lockaddr, 0, val)) /* got the lock */ 其中val可以简单地为锁的新预期所有者的常量或标识符。 我想知道的是x86(和x86_64)机器上两者之间是否存在任何显着的性能差异。 我知道这是一个相当广泛的问题,因为单个cpu模型之间的答案可能差异很大,但这是我要求的原因之一,而不仅仅是我可以访问的几个cpus的基准测试。

预取L1和L2的数据

在Agner Fog的手册“ C ++中的优化软件 ”第9.10节“大数据结构中的Cahce争论”中,他描述了当矩阵宽度等于称为临界步幅的情况时转置矩阵的问题。 在他的测试中,当宽度等于临界步幅时,L1中矩阵的成本增加40%。 如果矩阵更大并且仅适用于L2,则成本为600%! 这在表9.1中的文字中得到了很好的总结。 这与在为什么将512×512的矩阵转置比转换513×513的矩阵要慢得多一样是必不可少的。 后来他写道: 这种效果对于二级高速缓存争用而言比一级高速缓存争用强得多的原因是二级高速缓存不能一次预取多行。 所以我的问题与预取数据有关。 根据他的评论,我推断L1可以一次预取多个缓存行。 预取了多少? 据我所知,尝试编写代码来预取数据(例如使用_mm_prefetch)很少有用。 我读过的唯一例子是Prefetching Examples? 并且它只有O(10%)的改进(在某些机器上)。 Agner后来解释了这个: 原因是现代处理器由于无序执行和高级预测机制而自动预取数据。 现代微处理器能够自动预取包含具有不同步幅的多个流的常规访问模式的数据。 因此,如果可以使用固定步幅以常规模式排列数据访问,则不必显式预取数据。 那么CPU如何决定预取哪些数据,以及有哪些方法可以帮助CPU为预取做出更好的选择(例如“具有固定步幅的常规模式”)? 编辑:根据Leeor的评论,让我添加我的问题并使其更有趣。 与L1相比,为什么关键步幅对L2的影响要大得多? 编辑:我试图使用代码重现Agner Fog的表格为什么转换512×512的矩阵要比转置513×513矩阵慢得多? 我在Xeon E5 1620(Ivy Bridge)上以MSVC2013 64位版本模式运行它,它具有L1 32KB 8路,L2 256 KB 8路和L3 10MB 20路。 L1的最大矩阵大小约为90×90,L3的最大矩阵大小为256×256,L3的最大矩阵大小为1619。 Matrix Size Average Time 64×64 0.004251 0.004472 0.004412 (three times) 65×65 0.004422 0.004442 0.004632 (three […]

x86上的竞争条件

有人可以解释这个说法: shared variables x = 0, y = 0 Core 1 Core 2 x = 1; y = 1; r1 = y; r2 = x; 如何在x86处理器上使用r1 == 0和r2 == 0 ? 来自Bartosz Milewski的“并发语言” 。