使用gcc进行-mavx优化失败?
编辑下面的部分解决方案(编辑2),但我还有一个问题(见末尾) 我正在尝试编译下面的C程序,在Windows7上,32位,在a上运行(根据Windows系统信息)。如果我理解正确的话,这个处理器没有AVX扩展,所以发生一些事情是很自然的,我只是不确定到底是什么。最初,我在使用gcc进行优化,我尝试了-mavx,这是“偶然的” 下面的程序计算数字0的排列。。。n-1(以n为参数),以及每个排列的秩(其在该顺序中的位置)和“unrank”(从秩恢复排列),并检查所有这些是否正确。最后只打印“确定”或“错误”使用gcc进行-mavx优化失败?,c,gcc,mingw,avx,C,Gcc,Mingw,Avx,编辑下面的部分解决方案(编辑2),但我还有一个问题(见末尾) 我正在尝试编译下面的C程序,在Windows7上,32位,在a上运行(根据Windows系统信息)。如果我理解正确的话,这个处理器没有AVX扩展,所以发生一些事情是很自然的,我只是不确定到底是什么。最初,我在使用gcc进行优化,我尝试了-mavx,这是“偶然的” 下面的程序计算数字0的排列。。。n-1(以n为参数),以及每个排列的秩(其在该顺序中的位置)和“unrank”(从秩恢复排列),并检查所有这些是否正确。最后只打印“确定”或“
- 使用
,程序在我检查了所有整数输入的情况下正确运行(1“我不知道如何使它变短,同时仍然显示出这种奇怪的行为”--我建议将示例平分,与良好情况下的中间预期结果进行比较。@user3629249否,“I”的值有一次变为0(当最后一个排列被点击时:整个“a”都在减少)。由于“i”是在后面使用的,我不知道你怎么能想象循环什么都不做:它的唯一目的是找到“i”。可能是“for”后面的分号让你感到困扰。C允许这样做。@user3629249,你可能知道,gcc-O3
完全等同于for(a;b;C)d
。for循环中可能缺少“a”、“b”、“c”中的任何一个,而“d”可能会被简化为一个分号。W.r.t.你的最后一个问题:简单。这将是令人愤怒的(而且很慢)在每个SSE/AVX指令之前进行运行时检查,以验证CPU是否支持其指令集。使用a;而(b){d;c;}
承诺二进制文件将仅在支持AVX的CPU上运行;如果不是这样,x86 CPU将引发异常-mavx
(未定义的操作码),操作系统通过向有罪进程提供#UD
(非法指令)来作出反应信号,其默认操作是中止。@Iwillnotexistidnotexist实际上,它必须如此简单。快速检查显示,即使是除法0,或取消对空指针的引用,也会悄悄中止。我认为默认情况下会有消息,可能是因为我过去的Linux经验(我想他们会在Linux中打印消息?)实际上,不,'a'最后是数组{0,1,…n-1},因为当next_perm命中最后一个时(这是递减的),它在返回之前将其反转,因此“a”被重置为其初始状态。我的问题并不是像我所写的那样,程序真正做的是什么:SIGILL
按字典顺序查找下一个排列。next\u perm
计算排列在所有排列列表中的位置,而rank
则相反(从其位置计算perm)由于有n个排列,并且程序枚举了所有排列,花费的时间甚至超过了指数增长。此外,正如我在问题中所解释的,我编写程序是为了测试3个函数unrank
、next\u perm
和rank
是否正确地完成了它们的工作:它以字典或字典的形式计算所有排列der与next_perm一起,对于存储在“a”中的每一个,它计算它的位置,它必须是正确的位置(0,1,…n!-1),然后从这个位置计算回排列,它必须等于“a”。我在调用rank之前复制“a”,因为函数会破坏它的输入。举个例子(或字典顺序)这里的平均值。对于n=3,排列为011;021;1021;1201;2101;2110。其中有3!=6。unrank
#include <stdlib.h> #include <stdio.h> #define SWAP(a,b) {int c; c = a; a = b; b = c;} int next_perm(int n, int a[n]) { int i, j, k; for(i = n - 1; i > 0 && a[i - 1] > a[i]; i--); for(j = i, k = n - 1; j < k; j++, k--) SWAP(a[j], a[k]); if(i == 0) return 0; for(j = i--; a[j] < a[i]; j++); SWAP(a[i], a[j]); return 1; } #undef SWAP void copyvec(int n, int dst[n], int src[n]) { int i; for(i = 0; i < n; i++) { dst[i] = src[i]; } } int eqvec(int n, int a[n], int b[n]) { int i; for(i = 0; i < n; i++) { if(a[i] != b[i]) return 0; } return 1; } int rank(int n, int a[n]) { int v[n], i, j, r; v[n - 1] = 1; for(j = n - 2; j >= 0; j--) v[j] = v[j + 1]*(n - 1 - j); for(r = i = 0; ; i++) { for(j = i; j < n; j++) { if(a[j] > j) goto cont; } return r; cont: i = j; r += v[i]*(a[i] - i); for(j = i + 1; j < n; j++) { if(a[j] < a[i]) a[j]++; } } } void unrank(int n, int a[n], int p) { int v[n], i, j, r, s; v[n - 1] = 1; for(i = n - 2; i >= 0; i--) v[i] = v[i + 1]*(n - 1 - i); p %= n*v[0]; for(i = 0; i < n; i++) a[i] = i; for(i = 0; p > 0; i++) { for(; v[i] > p; i++); r = p/v[i]; p %= v[i]; for(s = a[j = i + r]; j >= i; j--) a[j] = a[j - 1]; a[i] = s; } } int main(int argc, char **argv) { int n, i, r, s = 0, q = 0; int *a = NULL, *b = NULL, *c = NULL; if(argc == 2 && (n = strtol(argv[1], NULL, 0)) > 0) { a = malloc(n*sizeof(int)); b = malloc(n*sizeof(int)); c = malloc(n*sizeof(int)); if(!a || !b || !c) { puts("Unable to allocate memory"); goto end; } else { for(i = 0; i < n; i++) a[i] = i; do { copyvec(n, b, a); r = rank(n, b); unrank(n, c, r); q |= s++ != r || !eqvec(n, a, c); } while(next_perm(n, a)); puts(q?"Error":"OK"); } } else { puts("perm n - Check all permutations of {0 ... n - 1}, with n > 0"); } end: if(a) free(a); if(b) free(b); if(c) free(c); return 0; }
#include <stdlib.h> #include <stdio.h> #define SWAP(a,b) {int c; c = a; a = b; b = c;} int next_perm(int n, int a[n]) { int i, j, k; for(i = n - 1; i > 0 && a[i - 1] > a[i]; i--); for(j = i, k = n - 1; j < k; j++, k--) SWAP(a[j], a[k]); if(i == 0) return 0; for(j = i--; a[j] < a[i]; j++); SWAP(a[i], a[j]); return 1; } #undef SWAP int main(int argc, char **argv) { int n, i, r, s = 0, q = 0, a[20]; n = strtol(argv[1], NULL, 0); for(i = 0; i < n; i++) a[i] = i; while(next_perm(n, a)); puts(q?"Error":"OK"); return 0; }
_next_perm: LFB0: push ebp push edi push esi push ebx mov ecx, DWORD PTR [esp+20] mov edx, DWORD PTR [esp+24] lea eax, [ecx-1] test eax, eax jle L12 mov edi, DWORD PTR [edx-4+ecx*4] cmp DWORD PTR [edx-8+ecx*4], edi mov ecx, eax jg L5 jmp L11 L28: mov esi, DWORD PTR [edx+ecx*4] cmp DWORD PTR [edx-4+ecx*4], esi jle L27 L5: sub ecx, 1 jne L28 L4: mov ebx, ecx L7: mov esi, DWORD PTR [edx+ebx*4] mov edi, DWORD PTR [edx+eax*4] mov DWORD PTR [edx+ebx*4], edi mov DWORD PTR [edx+eax*4], esi add ebx, 1 sub eax, 1 cmp ebx, eax jl L7 L2: xor eax, eax test ecx, ecx je L23 L11: sal ecx, 2 lea esi, [edx+ecx] lea ebp, [edx-4+ecx] mov ebx, DWORD PTR [esi] mov edi, DWORD PTR [ebp+0] cmp edi, ebx jle L9 lea eax, [edx+4+ecx] L10: mov esi, eax add eax, 4 mov ebx, DWORD PTR [eax-4] cmp ebx, edi jl L10 L9: mov DWORD PTR [ebp+0], ebx mov eax, 1 mov DWORD PTR [esi], edi L23: pop ebx pop esi pop edi pop ebp ret L27: cmp eax, ecx jg L4 jmp L11 L12: mov ecx, eax jmp L2
int main(int argc, char **argv) { int n, i, q = 0, a[20]; puts("X"); n = strtol(argv[1], NULL, 0); puts("Y"); for(i = 0; i < n; i++) a[i] = i; puts("Z"); while(next_perm(n, a)); puts(q?"Error":"OK"); return 0; }
_main: push ebp mov ebp, esp push edi push esi push ebx and esp, -16 sub esp, 96 call ___main mov DWORD PTR [esp], OFFSET FLAT:LC1 call _puts mov eax, DWORD PTR [ebp+12] mov DWORD PTR [esp+8], 0 mov DWORD PTR [esp+4], 0 mov eax, DWORD PTR [eax+4] mov DWORD PTR [esp], eax call _strtol mov DWORD PTR [esp], OFFSET FLAT:LC2 mov ebx, eax call _puts test ebx, ebx jle L17 lea edx, [ebx-4] lea ecx, [ebx-1] shr edx, 2 add edx, 1 cmp ecx, 3 lea eax, [0+edx*4] jbe L10 vmovdqa xmm1, XMMWORD PTR LC4 lea esi, [esp+16] xor ecx, ecx vmovdqa xmm0, XMMWORD PTR LC0 L5: mov edi, ecx add ecx, 1 sal edi, 4 cmp edx, ecx vmovaps XMMWORD PTR [esi+edi], xmm0 vpaddd xmm0, xmm0, xmm1 ja L5 cmp ebx, eax je L9 L4: lea edx, [eax+1] mov DWORD PTR [esp+16+eax*4], eax cmp ebx, edx jle L9 mov DWORD PTR [esp+16+edx*4], edx lea edx, [eax+2] cmp ebx, edx jle L9 add eax, 3 mov DWORD PTR [esp+16+edx*4], edx cmp ebx, eax jle L9 mov DWORD PTR [esp+16+eax*4], eax L9: mov DWORD PTR [esp], OFFSET FLAT:LC3 call _puts L3: mov DWORD PTR [esp+4], esi mov DWORD PTR [esp], ebx call _next_perm test eax, eax jne L3 mov DWORD PTR [esp], OFFSET FLAT:LC5 call _puts lea esp, [ebp-12] xor eax, eax pop ebx pop esi pop edi pop ebp ret L10: xor eax, eax lea esi, [esp+16] jmp L4 L17: lea esi, [esp+16] jmp L9
This code always results in: where parameter = n a[] = {0,0,2, 3, ...,n-2,n-1} b[] = {n-1, n-1, ... , n-1} c[] = {n-1, n-2, ... , 0} when it reaches the above conditions, then it exits with "OK" the amount of time spent executing the code climbs at an exponential rate as the value of the parameter is increased