为啥这个 C 语言中的 SIMD 示例代码可以用 minGW 编译,但可执行文件不能在我的 Windows 机器上运行?
Posted
技术标签:
【中文标题】为啥这个 C 语言中的 SIMD 示例代码可以用 minGW 编译,但可执行文件不能在我的 Windows 机器上运行?【英文标题】:Why does this SIMD example code in C compile with minGW but the executable doesn't run on my windows machine?为什么这个 C 语言中的 SIMD 示例代码可以用 minGW 编译,但可执行文件不能在我的 Windows 机器上运行? 【发布时间】:2014-12-11 21:50:21 【问题描述】:我正在学习 SIMD 的基础知识,因此我得到了一个简单的代码 sn-p 来了解 SSE 和 SSE2 的工作原理。
我最近安装了 minGW 来使用 gcc 在 windows 中编译 C 代码,而不是使用 Visual Studio 编译器。
这个例子的目的是把两个浮点数相加,然后乘以第三个。
包含的标头如下(我猜这些标头用于能够使用 SSE 内在函数):
#include <time.h>
#include <stdio.h>
#include <xmmintrin.h>
#include <pmmintrin.h>
#include <time.h>
#include <sys/time.h> // for timing
然后我有一个函数来检查现在是什么时候,比较计算之间的时间:
double now()
struct timeval t; double f_t;
gettimeofday(&t, NULL);
f_t = t.tv_usec; f_t = f_t/1000000.0; f_t +=t.tv_sec;
return f_t;
在“标量”意义上进行计算的函数如下:
void run_scalar()
unsigned int i;
for( i = 0; i < N; i++ )
rs[i] = (a[i]+b[i])*c[i];
这里是 sse2 函数的代码:
void run_sse2()
unsigned int i;
__m128 *mm_a = (__m128 *)a;
__m128 *mm_b = (__m128 *)b;
__m128 *mm_c = (__m128 *)c;
__m128 *mm_r = (__m128 *)rv;
for( i = 0; i <N/4; i++)
mm_r[i] = _mm_mul_ps(_mm_add_ps(mm_a[i],mm_b[i]),mm_c[i]);
向量的定义方式如下(N 是向量的大小,它在别处定义)并调用函数 init() 来初始化它们:
float a[N] __attribute__((aligned(16)));
float b[N] __attribute__((aligned(16)));
float c[N] __attribute__((aligned(16)));
float rs[N] __attribute__((aligned(16)));
float rv[N] __attribute__((aligned(16)));
void init()
unsigned int i;
for( i = 0; i < N; i++ )
a[i] = (float)rand () / RAND_MAX / N;
b[i] = (float)rand () / RAND_MAX / N;
c[i] = (float)rand () / RAND_MAX / N;
最后是调用函数并打印结果和计算时间的main。
int main()
double t;
init();
t = now();
run_scalar();
t = now()-t;
printf("S = %10.9f Temps du code scalaire : %f seconde(s)\n",1e5*sum(rs),t);
t = now();
run_sse2();
t = now()-t;
printf("S = %10.9f Temps du code vectoriel 2: %f seconde(s)\n",1e5*sum(rv),t);
总而言之,如果我使用“gcc -o vec vectorial.c -msse -msse2 -msse3”或“mingw32-gcc -o vec vectorial.c -msse -msse2 -msse3”的命令行编译此代码它编译没有任何问题,但由于某种原因,我无法在我的 Windows 机器上运行它,在命令提示符下我得到“拒绝访问”,屏幕上出现一条大消息,说“此应用程序无法在您的计算机上运行PC,要找到适合您 PC 的版本,请与软件发行商联系”。
我真的不明白发生了什么,我对 MinGW 或 C 也没有太多经验(只是在 Linux 机器上完成的 C++ 入门课程)。我尝试过使用不同的标头,因为我认为我的目标处理器可能与我 PC 上的处理器不同,但无法解决问题。我发现的大部分信息都很混乱。
有人可以帮助我了解发生了什么吗?在针对 Linux 平台进行编译的 minGW 配置中是否存在问题?代码中的某些东西在 Windows 中没有等效项吗?
我正在尝试在 64 位 Windows 8.1 电脑上运行它
编辑:尝试了下面链接的站点中建议的配置。输出保持不变。
如果我尝试通过 MSYS 运行,我会收到“错误文件编号” 如果我尝试通过命令提示符运行,我会得到 Access is Denied。
我猜有某种由权限引起的错误。尝试关闭防病毒和用户帐户控制,但仍然没有成功。
有什么想法吗?
【问题讨论】:
您的交叉编译器可能针对 x64,但您尝试在 32 位 Windows 上运行它? 你能运行一个用你的 GCC 编译的简单的“hello world”程序吗? 是的,我做到了,它运行良好:/ main() 不会编译干净。因为该函数具有预期的 int 返回,但代码缺少预期的 'return(0);'就在最后一个右大括号之前。我也没有看到子函数的原型,它应该列在主函数之前。 (子函数应该列在主函数之后)你需要在'gcc'之后添加-Wall参数,这样所有的警告都会显示出来。 我注意到您的代码没有任何问题,此外,您没有提供sum()
或N
的定义,但这不是问题。开关-msse -msse2
似乎不是必需的。
我能够在 Linux(Ubuntu x86_64,使用 gcc 4.8.2 和 4.6.3 编译,在 Atom D2700 和 AMD Athlon LE-1640 上)和 Windows7/64(使用 gcc 4.5.3 编译)上编译和运行您的代码(32 位)和 4.8.2(64 位),在 Core i3-4330 和 Core i7-4960X 上)。它运行没有问题。
您确定您的 CPU 支持所需的指令吗?你得到的错误代码到底是什么?您使用了哪种 MinGW 配置?出于好奇,我使用了http://win-builds.org/download.html 提供的那个,非常简单。
然而,使用优化标志-O3
创造了最好的结果——使用标量循环! -m64 -mtune=native -s
也很有用。
【讨论】:
关于最后一段:-O3
启用了自动矢量化,因此很可能“标量”版本被编译为根本不是标量的东西:)
我的 CPU 是 i7-4860HQ。我猜我的 minGW 没有配置为针对我的 CPU 或类似的东西,我对 MinGW 一点也不熟悉,所以我想这就是问题所在。我有 4.8.1 gcc 版本,我刚刚从他们的网站上下载了 MinGW,并按照说明进行了基本设置。我尝试按照网站上的安装说明使用您建议的那个,但没有运气。如果我通过 Msys 运行编译器并尝试运行我得到的 exe,编译会继续进行,没有错误或警告,但是当我尝试运行 exe 时,我得到“”错误文件号“
您对在哪里学习如何使用 MinGW 和 gcc 有什么建议吗?我真的觉得我不知道自己在做什么,而且 MinGW 网站不是很清晰或对新手友好。顺便说一句:感谢您的回答以上是关于为啥这个 C 语言中的 SIMD 示例代码可以用 minGW 编译,但可执行文件不能在我的 Windows 机器上运行?的主要内容,如果未能解决你的问题,请参考以下文章
这个 Delphi 6 位图修改代码可以用 SIMD 或其他方法加速吗?