在Hacker的喜悦中,有一种算法来计算两个(带符号)单词的双字产品 。 函数muldws1使用四次乘法和五次加法来计算两个单词的双字。 在该代码的末尾有一行注释掉 /* w[1] = u*v; // Alternative. */ 该替代方案使用五次乘法和四次加法,即它为乘法交换加法。 但我认为这种替代方法可以改进。 我还没有说过硬件。 让我们假设一个假设的CPU,它可以计算两个字但不是高位字的乘积的低位字(例如,对于32位字32×32到低32)。 在这种情况下,在我看来,这个算法可以改进。 这就是我假设的32位字(相同的概念适用于64位字)。 void muldws1_improved(int w[], int32_t x, int32_t y) { uint16_t xl = x; int16_t xh = x >> 16; uint16_t yl = y; int16_t yh = y >> 16; uint32 lo = x*y; int32_t t = xl*yh + xh*yl; […]
我正在研究并行编程概念,并尝试在单核上优化矩阵乘法示例。 到目前为止我提出的最快的实现如下: /* This routine performs a dgemm operation * C := C + A * B * where A, B, and C are lda-by-lda matrices stored in column-major format. * On exit, A and B maintain their input values. */ void square_dgemm (int n, double* A, double* B, double* C) { /* For each […]
我正在寻找一种更快的方法来完成这个: int is_empty(char * buf, int size) { int i; for(i = 0; i < size; i++) { if(buf[i] != 0) return 0; } return 1; } 我知道我正在寻找一个微观优化,除非在极端情况下,但我知道存在更快的方法,我很好奇它是什么。
我打算编写一个Game Boy模拟器( Z80是CPU,以防有人不熟悉它),在我做研究的时候,我发现了一些我不太确定的东西。 第一个是C是这里选择的编程语言。 这不是一个问题,但我想从今天的观点听取你的意见。 甚至不建议使用C ++。 我发现的第二件事是每个人都在使用每个操作码一个函数。 这似乎是合乎逻辑的,因为它只是一个函数调用,可能比为“ADD”指令设置一个函数更好地优化,然后你必须找出这里使用的寄存器。 但今天有多必要? 这是我应该坚持的东西,还是我应该改写我的模拟器,如果我注意到另一种可能更方便的方式就是不切割它(或多或少现代游戏机现在流入我的脑海)? 此外,一遍又一遍地编写一个“将该寄存器添加到该寄存器”的function,这种情况有点令人失望。 有没有办法从操作码映射或类似的东西自动化?
我正在寻找在512或更多字节的大缓冲区上popcount的最快方法。 我可以保证任何所需的对齐,缓冲区大小始终是2的幂。缓冲区对应于块分配,因此通常位是全部设置,没有设置,或者大多数设置有利于缓冲区的“左”,偶尔出洞。 我考虑过的一些解决方案是: 海湾合作委员会的__builtin_popcount Bitslice popcount_24words 计算位数,Brian Kernighan的方式 我对最快的解决方案感兴趣,它必须适用于属于core2或更新版本的32位x86芯片组。 SSE和SIMD引起了极大的兴趣。 我将在以下四核CPU上进行测试: matt@stanley:~/anacrolix/public/stackoverflow$ cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 15 model name : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz stepping : 11 cpu MHz : 1600.000 cache size : 4096 KB physical id : 0 siblings : […]
我知道-O1会自动打开某些标志。 但是,可以手动打开这些标志。 如果我没有指定-O1,那么仍然可以通过指定-O1打开的所有标志来获得-O1优化。 我试过了 -fthread-jumps -fcprop-registers -fguess-branch-probability 但它仍然没有做-O1优化。 我可以告诉我何时使用gprof,因为性能不是很好。 我打开哪些标志来获得-O1优化?
我正在编写一个非常重要的性能代码部分,我有一个关于用函数指针数组替换case语句(或if语句)的疯狂想法。 让我certificate一下; 这是正常版本: while(statement) { /* ‘option’ changes on every iteration */ switch(option) { case 0: /* simple task */ break; case 1: /* simple task */ break; case 2: /* simple task */ break; case 3: /* simple task */ break; } } 这是“回调函数”版本: void task0(void) { /* simple task */ } void task1(void) […]
在调试时,我经常进入memcpy和memset的手写程序集实现。 这些通常使用流指令(如果可用),循环展开,对齐优化等实现…我最近也遇到了由于glibc中的memcpy优化而导致的“错误” 。 问题是:为什么硬件制造商(英特尔,AMD)不能优化具体情况 rep stos 和 rep movs 被认可,并尽可能快地填写和复制他们自己的架构?
请考虑以下代码: void error_handling(); bool method_impl(); bool method() { const bool res = method_impl(); if (res == false) { error_handling(); return false; } return true; } 我知道method_impl()将返回true 99.999%(是的,三位小数)的时间,但我的编译器没有。 method()在时间消耗方面是部分关键的。 我应该重写method() (并使其不太可读)以确保只有当method_impl()返回false时才会发生跳转? 如果有,怎么样? 我应该让编译器为我做这项工作吗? 我应该让我的CPU的分支预测为我做的工作吗?
Arstechnia最近有一篇文章为什么一些编程语言比其他语言更快 。 它比较了Fortran和C,并提到了求和数组。 在Fortran中,假设数组不重叠,因此可以进一步优化。 在C / C ++中,指向相同类型的指针可能会重叠,因此通常不能使用此优化。 但是,在C / C ++中,可以使用restrict或__restrict关键字告诉编译器不要假设指针重叠。 所以我开始研究自动矢量化。 以下代码在GCC和MSVC中进行矢量化 void dot_int(int *a, int *b, int *c, int n) { for(int i=0; i<n; i++) { c[i] = a[i] + b[i]; } } 我使用和不使用重叠数组测试了它,它得到了正确的结果。 但是,我使用SSE手动向量化循环的方式不能处理重叠数组。 int i=0; for(; i<n-3; i+=4) { __m128i a4 = _mm_loadu_si128((__m128i*)&a[i]); __m128i b4 = _mm_loadu_si128((__m128i*)&b[i]); __m128i c4 = […]