我正在尝试使用MinGW编译ATLAS。我开始解决问题了,但是现在我遇到了一个简单的问题:ATLAS的Makefile尝试使用MinGW提供的uname.exe来探测操作系统。
如果我运行MinGW shell(sh.exe),我可以调用uname。如果我打开Windows命令提示符,我可以调用uname(所以%PATH%变量和$ PATH变量设置正确)。
代码在内部调用类似system(“uname -s> \ tempfilneame& 2> 1”)。主要问题是(当我分析FileMon的输出时)应用程序(sh.exe)创建cmd.exe进程,而不是执行我的命令,但找不到uname。如果我将代码系统(“d:/.../ bin / uname -s> \ tempfilename& 2> 1”)添加到代码中,一切正常。所以它应该是PATH变量的问题。如果它不是必要的,我不会修改代码中的每一个调用。问题是:cmd.exe进程启动时有什么特别之处,所以它无法识别uname,我怎么能解决这个问题。
答案 0 :(得分:2)
Msys的目的是提供一个最小的准 - " * nix" (即,非POSIX)Bourne Shell(一个" * nix"命令行解释器),在其中执行程序,命令和shell脚本,就好像在" * nix"系统(参考http://www.mingw.org/)。无论出于何种原因,如果希望从MS Windows命令行解释器(cmd.exe)运行MinGW / bin 和 Msys / 1.0 / bin可执行文件,MS Windows环境%PATH%变量必须包含通往这两个" bin"子目录 - 例如"。; C:\ MinGW \ bin; C:\ MinGW \ msys \ 1.0 \ bin;%PATH%"。
以下信息引用严格来使用由MinGW提供的GCC 4.6.2编译器套件从msys.bat调用的Msys sh.exe中构建ATLAS库。
确保您的Msys $ PATH环境变量包含"。:MinGW和Msys bin目录的路径" - 即"。:/ C / MinGW / bin:/C/MinGW/msys/1.0/bin:$ PATH"如果你安装MinGW和Msys的地方(这应该在发生sh登录时由/ etc / profile脚本完成,如\ msys \ 1.0 \ msys.bat文件)。
必须对使用system()函数调用shell命令或可执行文件(#34; make")的任何ATLAS程序语句进行以下更改:
1)改变" ./可执行文件" to"。\\ executable"或"可执行文件"由于MS Windows cmd.exe shell(或更准确地说,被称为MS Windows系统库例程)解释了" ./ executable"作为可执行文件'。'使用命令选项' / executable',因此错误消息:"'。'不被识别为内部或外部命令,可操作程序或批处理文件。"确保使用" -v 2"调用ATLAS / configure。为了找到任何有问题的system()调用 - 只有少数!!!
ATLAS/bin/atlas_install.c
ATLAS/CONFIG/src/atlbench.c
ATLAS/CONFIG/src/config.c
ATLAS/tune/blas/gemm/userindex.c
ATLAS/tune/blas/ger/r1search.c
ATLAS/tune/sysinfo/emit_buildinfo.c
2)改变"命令;命令"到"命令&&命令"由于MS Windows cmd.exe不接受使用&#39 ;;'的复合命令语句。分隔符与其他" * nix"贝壳或"制作"。
3)对于传递给system()调用的命令,在sprintf()语句中用双引号分隔字符串格式说明符替换任何出现的单引号;特别是在ATLAS / CONFIG / src / config.c文件的SpewItForth函数中。例如,更改" ...'%s' ..."到" ... \"%s \" ...&#34 ;.这不是" make"使用system()调用调用的命令。由于MS Windows cmd.exe shell期望CRLF终止终止,因此必须对ATLAS / bin / atlas_install.c和ATLAS / tune / sysinfo / emit_buildinfo.c文件进行以下更改。
在ATLAS / bin / atlas_install.c,第133行来自:
if ( (sp == NULL) || (str[0] == '\0') || (str[0] == '\n') )
为:
if ( (sp == NULL) || (str[0] == '\0') || (str[0] == '\r') || (str[0] == '\n') )
第165行,来自:
else if (ln[0] == '\0' || ln[0] == '\n') ch=def;
为:
else if (ln[0] == '\0' || ln[0] == '\r' || ln[0] == '\n') ch=def;
第175行,来自:
else if (ln[0] == '\0' || ln[0] == '\n') ch=def;
为:
else if (ln[0] == '\0' || ln[0] == '\r' || ln[0] == '\n') ch=def;
在ATLAS / tune / sysinfo / emit_buildinfo.c,第66行:
for (i=0; ln[i]; i++) if (ln[i] == '"' || ln[i] == '`') ln[i] = '\'';
为:
for (i=0; ln[i]; i++) if (ln[i] == '"' || ln[i] == '`') ln[i] = '\"';
第68行:
for (i--; i >= 0 && (ln[i] == ' ' || ln[i] == '\n' || ln[i] == '\t'); i--);
为:
for (i--; i >= 0 && (ln[i] == ' ' || ln[i] == '\r' || ln[i] == '\n' || ln[i] == '\t'); i--);
此外,在ATLAS / tune / sysinfo / emit_buildinfo.c文件中,更改:
if (CommandOneLine("date",DATE)) strcpy(DATE, "UNKNOWN");
为:
if (CommandOneLine("date /t",DATE)) strcpy(DATE, "UNKNOWN");
自MS Windows cmd.exe" date"命令将提示"输入新日期:(mm-dd-yy)"并等待永远不会进入的回复。
虽然我对每个受影响的文件进行了上述更改,但是遵守基本的软件工程和配置管理原则会要求将重复的代码合并到单个程序中,并使用某种形式的#t; #if定义(ATL_OS_WinNT)&& ;定义(__ MINGW32 __)"处理指令,以防止变更对ATLAS的安装产生不利影响,其他" * nix"操作系统。在这方面,我不建议使用"补丁"将MinGW32特定更改合并到ATLAS发行版的方法,但将必要的更改合并到最新的ATLAS开发版本中。当然,"修补"可能是修复不支持的ATLAS版本的唯一选择。
在过去的几天里,我能够使用下载的MinGW,Msys和GCC 4.6.2编译器套件构建调优的ATLAS 3.8.4静态库:
http://sourceforge.net/projects/mingw/files/
并在11岁的戴尔工作站530上安装了mingw-get-inst-20111118.exe,配备双Intel Xeon(Pentium 4,MMX,SSE和SSE2 [L1缓存8 KB,L2缓存256 KB],但没有超线程)1.5 GHz处理器,400 MHz FSB和1024 MB运行Windows 2000 Professional SP4的RDRAM。
上述修改并不全面,但应该会让您更进一步。我计划记录我对ATLAS 3.8.4发行版的所有更改,并将其发布在Windows上的#34; ATLAS"在验证我的调优配置并使用LAPACK-3.4.0完成共享库构建后,http://sourceforge.net/projects/math-atlas/forums/上的论坛。
我希望这些信息对您和其他在Windows平台上尝试使用MinGW和不使用 Cygwin进行ATLAS构建的人有所帮助。
特别说明:
使用将输出定向到从调用tmpnam()获得的临时文件名的命令调用system()将导致在当前驱动器的根目录中创建临时文件。临时文件名以' \\'为前缀,在MinGW / include / stdio.h中定义(参见P_tmpdir)。
重要附录:
(A)确保在使用' -s'指定源和构建目录时使用完整路径名。和' -b' ATLAS / configure的命令选项。在我的例子中,以下sh脚本显示了我如何从ATLAS_build调用ATLAS / configure:
#!/bin/sh
SRCDIR=/g/Progs/MinGW/msys/1.0/home/GaryD/temp/ATLAS
BLDDIR=/g/Progs/MinGW/msys/1.0/home/GaryD/temp/ATLAS_build
LAPACK=/g/Progs/MinGW/lib/gcc/mingw32/4.6.2/liblapack.dll.a
CC=gcc
C_DEFS="-D c -DL2SIZE=262144" # Not used, set using -f 256
F_DEFS="-D f ''" # Not used, let configure set these
C_FLGS="--cc=$CC --with-netlib-lapack=$LAPACK"
D_FLGS="-d s $SRCDIR -d b $BLDDIR"
A_FLGS="-O 8 -s 1 -A 20 -V 8 -b 32 -f 256 -t 2 -m 1495"
S_FLGS="-Si bozol1 1 -Si archdef 0 -Si cputhrchk 0"
$SRCDIR/configure $C_FLGS -v 2 $D_FLGS $A_FLGS $S_FLGS
(B)我认为首选构建目录被假定为ATLAS源目录下的子目录,例如ATLAS / ATLAS_build,因为ATLAS无法找到文件../../CONFIG/error.txt /bin/atlas_install.c如果源和构建目录处于同一级别。
(C)不要犯错我做的假设' -m ####' configure选项隐式创建了一个' -D c DPentiumCPS = ####'配置标志。您可能需要明确传递' -D c -DPentiumCPS = ####'或者' -D c -DWALL'如第3.4节所述,"改变ATLAS的时间安排"," ATLAS安装指南"可以在这里查看:
http://math-atlas.sourceforge.net/atlas_install/atlas_install.html#SECTION00044000000000000000
通过不使用周期精确的墙上计时器,来自健全性测试的结果,例如来自" xsslvtst.exe -n 167 -r 83 -O 2 cr -U 2 u l"的结果,类似于此:
ORD UPLO N NRHS lda ldb TIME MFLOP RESID
=== ==== ====== ====== ====== ====== ========= ======== ===========
C U 167 83 167 167 0.015 257.82 1.762022e-003
C L 167 83 167 167 0.016 241.70 1.870298e-003
R U 167 83 167 167 0.000 2229332063710638100.00 1.870298e-003
R L 167 83 167 167 0.000 2229332063710638100.00 1.762022e-003
4 TESTS RUN, ALL PASSED.
每次调用测试都会为MFLOP产生不同的虚假值,这可能是由非常非常非常小的非零值进行算术除法。在使用' -D c -DWALL'重建ATLAS之后,这些MFLOP结果(毫无疑问是其他时间措施)得到了纠正。
(D)ATLAS / CONFIG / src / probe_OS.c第35行需要检查MinGW:
else if(strstr(ln, "WIN") || strstr(ln, "MINGW"))
并在" IRunArchInfo_linux:xarchinfo_linux"之后插入以下内容:在ATLAS / CONFIG / src / Makefile中阻塞(只需剪切,粘贴和编辑Makefile中的IRunArchInfo_linux块):
IRunArchInfo_winnt: xarchinfo_x86
- rm -f config0.out
$(MAKE) $(atlrun) atldir=$(mydir) exe=xarchinfo_x86 args="$(args)" \
redir=config0.out
- cat config0.out
(E)gcc-4行可能需要在ATLAS / CONFIG / src / atlconf.txt文件中更改为gcc,因为MinGW gcc可执行文件只是gcc.exe而不是gcc-4.exe这个最新版本的MinGW32 gcc编译器套件。使用configure标志来覆盖编译器选择和更改/附加编译标志可能比ATLAS开发人员编辑atlconf.txt文件(参见" ATLAS安装指南"第3.2节)更受欢迎;但我很不耐烦。
(F)如果您使用' -V 8'指定SSE2对于我的架构,ATLAS / configure选项,必须对ATLAS / include / atlas_asm.h文件进行以下更改。
第133行:
#if defined(ATL_SSE1) && !defined(ATL_3DNow)
为:
#if (defined(ATL_SSE1) || defined(ATL_SSE2)) && !defined(ATL_3DNow)