Tag: 优化

C for循环索引:在新CPU中前向索引更快?

在我订阅的邮件列表中,两位相当知识渊博的(IMO)程序员正在讨论一些优化的代码,并说出以下内容: 在5 – 8年前发布的CPU上,向后循环迭代的速度稍快( 例如, for (int i=x-1; i>=0; i–) {…} ),因为将i与零进行比较比将其与其他数字相比更有效。 但是对于非常近期的CPU( 例如从2008年到2009年),推测性加载器逻辑使得如果for循环向前迭代它会更好( 例如 for (int i=0; i< x; i++) {…} ) 。 我的问题是,这是真的吗? 最近是否更改了CPU实现,这样前向循环迭代现在比后向迭代有优势? 如果是这样,对此有何解释? 即改变了什么? (是的,我知道,过早的优化是所有邪恶的根源,在考虑微优化之前检查我的算法等等…大多数我只是好奇)

查询gcc的-ffunction-section和-fdata-sections选项

以下在GCC页面中提到的function部分和数据部分选项: -ffunction-sections -fdata-sections 如果目标支持任意节,则将每个函数或数据项放入输出文件中的自己的部分。 函数名称或数据项名称确定输出文件中节的名称。 在链接器可以执行优化以改善指令空间中引用的局部性的系统上使用这些选项。 大多数使用ELF对象格式的系统和运行Solaris 2的SPARC处理器都具有这种优化的链接器。 AIX可能会在将来进行这些优化。 只有在这样做的重大好处时才使用这些选项。 指定这些选项时,汇编器和链接器将创建更大的对象和可执行文件,并且速度也会更慢。 如果指定此选项,则无法在所有系统上使用gprof,如果同时指定此选项和-g,则可能在调试时遇到问题。 我的印象是这些选项有助于减少可执行文件的大小。 为什么这个页面会说它会创建更大的可执行文件? 我错过了什么吗?

在GCC中生成没有cmp指令的循环

我有一些紧凑的循环,我正在尝试使用GCC和内在函数进行优化。 考虑例如以下function。 void triad(float *x, float *y, float *z, const int n) { float k = 3.14159f; int i; __m256 k4 = _mm256_set1_ps(k); for(i=0; i<n; i+=8) { _mm256_store_ps(&z[i], _mm256_add_ps(_mm256_load_ps(&x[i]), _mm256_mul_ps(k4, _mm256_load_ps(&y[i])))); } } 这会产生这样的主循环 20: vmulps ymm0,ymm1,[rsi+rax*1] 25: vaddps ymm0,ymm0,[rdi+rax*1] 2a: vmovaps [rdx+rax*1],ymm0 2f: add rax,0x20 33: cmp rax,rcx 36: jne 20 但是cmp指令是不必要的。 而不是让rax从零开始并在sizeof(float)*n处完成,我们可以将基本指针( rsi […]

最优化的计算C模数的方法

我用C计算模数的成本最小化。假设我有一个数字x而n是将x除以的数字 当n == 65536(恰好是2 ^ 16)时: mod = x%n(由GCC制作的11条assembly说明)或 mod = x&0xffff等于mod = x&65535(4个汇编指令) 因此,海湾合作委员会并未对此进行优化。 在我的情况下,n不是x ^(int),而是小于2 ^ 16的最大素数,即65521 正如我在n == 2 ^ 16中所展示的那样,逐位运算可以优化计算。 当n == 65521计算模数时,我可以执行哪些按位操作。

GCC SSE代码优化

这篇文章与我几天前发布的另一篇文章密切相关。 这一次,我编写了一个简单的代码,它只添加了一对元素数组,将结果乘以另一个数组中的值并将其存储在第四个数组中,所有变量浮点数都是双精度类型。 我制作了两个版本的代码:一个是SSE指令,使用调用而另一个没有它我然后用gcc和-O0优化级别编译它们。 我在下面写下: // SSE VERSION #define N 10000 #define NTIMES 100000 #include #include #include #include double a[N] __attribute__((aligned(16))); double b[N] __attribute__((aligned(16))); double c[N] __attribute__((aligned(16))); double r[N] __attribute__((aligned(16))); int main(void){ int i, times; for( times = 0; times < NTIMES; times++ ){ for( i = 0; i <N; i+= 2){ __m128d mm_a = _mm_load_pd( […]

使用C / Intel程序集,测试128字节内存块是否包含全零的最快方法是什么?

继续我的第一个问题,我正在尝试优化通过VTune分析64位C程序找到的内存热点。 特别是,我想找到一种最快的方法来测试一个128字节的内存块是否包含全零。 您可以假设内存块有任何所需的内存对齐方式; 我使用64字节对齐。 我使用的是配备Intel Ivy Bridge Core i7 3770处理器和32 GB内存的PC以及免费版的Microsoft vs2010 C编译器。 我的第一次尝试是: const char* bytevecM; // 4 GB block of memory, 64-byte aligned size_t* psz; // size_t is 64-bits // … // “m7 & 0xffffff80” selects the 128 byte block to test for all zeros psz = (size_t*)&bytevecM[(unsigned int)m7 & 0xffffff80]; if (psz[0] […]

什么是计算2模数的大功率的最快方法

对于1 <= N <= 1000000000 ,我需要计算2 N mod 1000000007 ,它必须非常快! 我目前的做法是: ull power_of_2_mod(ull n) { ull result = 1; if (n <= 63) { result <<= n; result = result % 1000000007; } else { ull one = 1; one < 63) { result = ((result % 1000000007) * (one % 1000000007)) % 1000000007; n […]

我们还应该优化“小”吗?

我正在改变我的for循环以使用++i而不是i++来增加并且开始思考,这是否真的有必要了? 当然,今天的编译器会自己进行优化。 在本文中, http://leto.net/docs/C-optimization.php ,从1997年开始迈克尔·李进入其他优化,如内联,循环展开,循环干扰,循环反转,强度降低等等。 这些仍然相关吗? 我们应该进行哪些低级代码优化,以及我们可以安全地忽略哪些优化? 编辑:这与过早优化无关。 已经做出了优化的决定。 现在问题是什么是最有效的方法。 轶事:我曾经审查了一个要求规范:“程序员应该离开一个而不是乘以2”。

什么是在x86上提供无分支FP min和max的指令?

引用(感谢作者开发和共享算法!): Fast, Branchless Ray/Bounding Box Intersections 由于现代浮点指令集可以在没有分支的情况下计算最小值和最大值 作者的相应代码就是 dmnsn_min(double a, double b) { return a < b ? a : b; } 我熟悉例如_mm_max_ps ,但这是一个向量指令。 上面的代码显然是用于标量forms。 题: 什么是x86上的标量无分支minmax指令? 这是一系列指令吗? 假设它将被应用,或者如何调用它是否安全? 关于min / max的无分支问题是否有意义? 根据我的理解,对于光线跟踪器和/或其他视觉软件,给定光线盒交叉例程,分支预测器没有可靠的模式来拾取,因此消除分支确实有意义。 我是对的吗? 最重要的是,所讨论的算法是围绕(+/-)INFINITY进行比较而建立的。 这是可靠的,我们正在讨论的(未知)指令和浮点标准吗? 以防万一:我熟悉在C ++中使用min和max函数 ,相信它是相关的,但不是我的问题。

对浮点数和双精度快速乘法/除2(C / C ++)

在我正在编写的软件中,我正在进行数百万次乘法或除以2(或2的幂)的值。 我真的希望这些值为int以便我可以访问bitshift运算符 int a = 1; int b = a<<24 但是,我不能,而且我必须坚持双打。 我的问题是: 由于存在双精度(符号,指数,尾数)的标准表示,有没有办法使用指数来获得2的幂的快速乘法/除法 ? 我甚至可以假设位数将被修复(该软件将在总是具有64位长的双倍的机器上工作) PS:是的,该算法主要只执行这些操作。 这是瓶颈(它已经是multithreading的)。 编辑:或者我完全错了,聪明的编译器已经为我优化了一些东西? 临时结果(用Qt测量时间,矫枉过正,但我​​不在乎): #include #include #include #include #include using namespace std; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); while(true) { QElapsedTimer timer; timer.start(); int n=100000000; volatile double d=12.4; volatile double D; for(unsigned int i=0; i<n; ++i) { […]