Tag: 优化

为什么++我可能与i + = 1表现不同

显然是在阅读了旧标题之后 为什么像is ++i fster than i+=1这样的问题甚至存在 人们没有仔细阅读这个问题本身。 问题不在于人们提出要求的理由! 这就是为什么编译器会在++i和i+=1之间产生差异,并且有任何可能出现的情况都是有意义的。 虽然我很欣赏你所有的诙谐和深刻的评论,但我的问题并非如此。 好吧,好吧,让我试着用另一种方式提出问题,我希望我的英语足够好,这次我可以表达自己而不会被误解,所以请阅读 。 让我们说有人在一本10年前的书中读到这个: 使用++ i over i = i + 1可以获得性能优势。 我并不热衷于这个特定的例子,而是更多或更少地谈论。 显然,当作者写这本书时,对他来说是有道理的,他不仅仅是弥补了这一点。 我们知道现代编译器不关心你是使用++i , i+=1还是i = i + 1 ,代码将被优化并且我们将具有相同的asm输出。 这似乎很合乎逻辑:如果两个操作做同样的事情并且具有相同的结果,则没有理由将++i编译成一个东西,并且i+=1变成另一个东西。 但是自从这本书作者写下来之后 ,他已经看到了它的不同之处! 这意味着某些编译器实际上会为这两行产生不同的输出。 这意味着制作编译器的人有一些理由以不同的方式处理++i和i+=1 。 我的问题是他们为什么会这样做? 是不是因为那些日子很难/不可能使编译器足够先进以进行这样的优化? 或者也许在一些非常具体的平台/硬件上/在某些特殊情况下,实际上有必要在++i和i+=1以及其他类似东西之间做出改变? 或者它可能取决于变量类型? 或者编译器开发者只是懒惰?

嵌套循环,内循环并行化,重用线程

免责声明:以下示例只是一个快速了解问题的虚拟示例。 如果您正在考虑现实问题,请考虑任何动态编程。 问题:我们有一个n * m矩阵,我们想要复制上一行中的元素,如下面的代码所示: for (i = 1; i < n; i++) for (j = 0; j < m; j++) x[i][j] = x[i-1][j]; 方法:必须按顺序执行外循环迭代,它们将按顺序执行。 内环可以并行化。 我们希望最小化创建和杀死线程的开销,因此我们只想创建一次线程团队,但是,这似乎是OpenMP中不可能完成的任务。 #pragma omp parallel private(j) { for (i = 1; i < n; i++) { #pragma omp for scheduled(dynamic) for (j = 0; j < m; j++) x[i][j] = […]

MS编译器优化替换函数中的变量?

我不知道如何解释我所看到的行为,但这里有。 我有一个函数foo,它有三个参数,一个指针,一个int和另一个指针。 当我在foo内部断点时,我可以清楚地看到所有变量都是它们应该是的值。 但是,当我退出局部变量声明时,其中一个参数(int)突然变为零。 但是,函数的其余部分就像原始值一样执行,所以一切都很好。 这不会在完全调试中发生,但会在常规调试中发生。 这是某种优化吗? 如果是这样,它叫什么,我在哪里可以得到细节? 例: void foo(void *A, int B, void *C) { // B == 5 int X = 3; char *Y = getSomeStaticString(); // … some other variable declarations like the above // B, according to the debugger, is now 0 if (B == 5) { // But this […]

使用SIMD优化1D热方程

我正在使用CFD代码(用于计算流体动态)。 我最近有机会在我的一个循环中看到英特尔编译器使用SSE,在这个循环中为计算性能增加了近2倍的因子。 但是,使用SSE和SIMD指令似乎更像是运气。 大多数情况下,编译器什么都不做。 我正在尝试强制使用SSE,考虑到AVX指令将在不久的将来强化这一方面。 我做了一个简单的1D热转印代码。 它由两个阶段组成,使用另一个阶段的结果(U0 – > U1,然后是U1 – > U0,然后是U0 – > U1等)。 当它迭代时,它会收敛到稳定的解决方案。 主代码中的大部分循环都使用相同的计算方式。 (有限差分)。 但是,我的代码比普通循环慢两倍。 结果是相同的,因此计算是一致的。 我弄错了吗? 在使用Westmer进行测试之前,我正在使用Core 2来测试循环。 这是代码,带有SSE循环,然后是引用循环: #include #include #include //#include #define n1 1004 #define niter 200000 int i,j,t; double U0[n1] __attribute__ ((aligned(16))); double U1[n1] __attribute__ ((aligned(16))); double Dx,Dy,Lx,Ly,InvDxDx,Dt,alpha,totaltime,Stab,DtAlpha,DxDx; __m128d vmmx00; __m128d vmmx01; __m128d vmmx02; __m128d vmmx10; […]

寻找最快的汉明距离C实现

我想找到两个等长的字符串有多少个不同的字符。 我发现xoring算法被认为是最快的,但它们返回以位表示的距离。 我希望结果以字符表示。 假设“pet”和“pit”的距离1以字符表示,但“e”和“i”可能有两个不同的位,因此xoring返回2。 我写的函数是: // na = length of both strings unsigned int HammingDistance(const char* a, unsigned int na, const char* b) { unsigned int num_mismatches = 0; while (na) { if (*a != *b) ++num_mismatches; –na; ++a; ++b; } return num_mismatches; } 会变得更快吗? 也许使用一些较低级别的命令或实现不同的算法? 系统:Intel Xeon X5650上的Gcc 4.7.2 谢谢

用于GCC划分的SIMD(SSE)指令

如果可能,我想使用SSE指令优化以下代码段: /* * the data structure */ typedef struct v3d v3d; struct v3d { double x; double y; double z; } tmp = { 1.0, 2.0, 3.0 }; /* * the part that should be “optimized” */ tmp.x /= 4.0; tmp.y /= 4.0; tmp.z /= 4.0; 这有可能吗?

使用可能/不太可能的提示是否有任何性能测试结果?

gcc提供可能/不太可能的提示 ,帮助编译器生成具有更好分支预测的机器代码。 有没有关于如何正确使用或不使用这些提示影响某些真实系统上实际代码性能的数据?

如何以更优化的方式提取一点?

我今天接受了采访,他们要求我写两个“C”函数,一个用于提取单个位,另一个用于从字符中提取一系列位。 我花了一段时间想出了这些方法。 int extractBit(char byte, int pos) { assert( (pos >= 0) && (pos < 8) ); return ( ( byte & (1<> pos); } char extractBitRange(char byte, int startingPos, int offset) { assert( ( (startingPos + offset) >= 0) && ( (startingPos + offset) > startingPos ) & ~(0xff << (offset + 1)); } […]

GCC优化对比特操作的有效性

以下是在x86-64上设置C中的单个位的两种方法: inline void SetBitC(long *array, int bit) { //Pure C version *array |= 1<<bit; } inline void SetBitASM(long *array, int bit) { // Using inline x86 assembly asm("bts %1,%0" : "+r" (*array) : "g" (bit)); } 使用带有-O3 -march=core2选项的GCC 4.3,当使用常量bit时,C版本需要大约90%的时间 。 (两个版本编译为完全相同的汇编代码,除了C版本使用or [1<<num],%rax指令而不是bts [num],%rax指令) 与变量bit ,C版本表现更好,但仍然明显慢于内联汇编。 重置,切换和检查位具有类似的结果。 为什么GCC对这种常见操作的优化程度如此之差? 我是否在使用C版本做错了什么? 编辑:对不起,等待很长时间,这是我用来进行基准测试的代码。 它实际上是一个简单的编程问题… int main() { // Get […]

快速逐字节替换if

我有一个函数可以将二进制数据从一个区域复制到另一个区域,但前提是这些字节与特定值不同。 这是一个代码示例: void copy_if(char* src, char* dest, size_t size, char ignore) { for (size_t i = 0; i < size; ++i) { if (src[i] != ignore) dest[i] = src[i]; } } 问题是这对我目前的需求来说太慢了。 有没有办法以更快的方式获得相同的结果? 更新:基于答案,我尝试了两个新的实现: void copy_if_vectorized(const uint8_t* src, uint8_t* dest, size_t size, char ignore) { for (size_t i = 0; i < size; ++i) { […]