提交 d29aac44 authored 作者: Pascal Lamblin's avatar Pascal Lamblin

Refactor code for trying to compile/run some code

上级 1308dcf2
...@@ -1484,37 +1484,51 @@ class GCC_compiler(object): ...@@ -1484,37 +1484,51 @@ class GCC_compiler(object):
return cxxflags return cxxflags
@staticmethod @staticmethod
def try_flags(flag_list): def try_compile_tmp(src_code, tmp_prefix='', flags=(), try_run=False):
''' """Try to compile (and run) a test program.
Try to compile a dummy file with these flags.
Returns True if compilation was successful, False if there This is useful in various occasions, to check if libraries
were errors. or compilers are behaving as expected.
'''
If try_run is True, the src_code is assumed to be executable,
and will be run.
If try_run is False, returns the compilation status.
If try_run is False, returns a (compile_status, run_status) pair.
"""
if not theano.config.cxx: if not theano.config.cxx:
return False return False
rval = True flags = list(flags)
compilation_ok = True
try: try:
code = """ fd, path = tempfile.mkstemp(suffix='.c', prefix=tmp_prefix)
int main(int argc, char** argv) exe_path = path[:-2]
{
return 0;
}
"""
fd, path = tempfile.mkstemp(suffix='.c', prefix='try_flags_')
dummy_stdin = open(os.devnull) dummy_stdin = open(os.devnull)
try: try:
os.write(fd, code) os.write(fd, src_code)
os.close(fd) os.close(fd)
fd = None fd = None
proc = call_subprocess_Popen(['g++', path] + flag_list, proc = call_subprocess_Popen(
['g++', path, '-o', exe_path] + flags,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=dummy_stdin.fileno()) stdin=dummy_stdin.fileno())
proc.wait() proc.wait()
if proc.returncode != 0: if proc.returncode != 0:
rval = False compilation_ok = False
elif try_run:
# Try to execute the program
run_ok = False
try:
proc = call_subprocess_Popen([exe_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=dummy_stdin.fileno())
proc.wait()
run_ok = (proc.returncode == 0)
finally:
os.remove(exe_path)
finally: finally:
del dummy_stdin del dummy_stdin
try: try:
...@@ -1522,9 +1536,34 @@ class GCC_compiler(object): ...@@ -1522,9 +1536,34 @@ class GCC_compiler(object):
os.close(fd) os.close(fd)
finally: finally:
os.remove(path) os.remove(path)
except OSError, e: except OSError, e:
rval = False compilation_ok = False
return rval
if not try_run:
return compilation_ok
else:
return (compilation_ok, run_ok)
@staticmethod
def try_flags(flag_list):
'''
Try to compile a dummy file with these flags.
Returns True if compilation was successful, False if there
were errors.
'''
if not theano.config.cxx:
return False
code = """
int main(int argc, char** argv)
{
return 0;
}
"""
return GCC_compiler.try_compile_tmp(code, tmp_prefix='try_flags_',
flags=flag_list, try_run=False)
@staticmethod @staticmethod
def compile_str(module_name, src_code, location=None, def compile_str(module_name, src_code, location=None,
......
...@@ -12,18 +12,15 @@ __contact__ = "theano-dev <theano-dev@googlegroups.com>" ...@@ -12,18 +12,15 @@ __contact__ = "theano-dev <theano-dev@googlegroups.com>"
__docformat__ = "restructuredtext en" __docformat__ = "restructuredtext en"
import logging import logging
import os
import subprocess
import tempfile
import warnings import warnings
import theano import theano
from theano import config from theano import config
from theano.misc.windows import call_subprocess_Popen
import theano.gof.cc import theano.gof.cc
from theano.gof import graph from theano.gof import graph
from theano.gof import utils from theano.gof import utils
from theano.gof.cmodule import GCC_compiler
from theano.gof.fg import FunctionGraph from theano.gof.fg import FunctionGraph
...@@ -770,42 +767,22 @@ class OpenMPOp(Op): ...@@ -770,42 +767,22 @@ class OpenMPOp(Op):
@staticmethod @staticmethod
def test_gxx_support(): def test_gxx_support():
default_openmp = True
try:
code = """ code = """
#include <omp.h> #include <omp.h>
int main( int argc, const char* argv[] ) int main( int argc, const char* argv[] )
{ {
int res[10]; int res[10];
for(int i=0; i < 10; i++){ for(int i=0; i < 10; i++){
res[i] = i; res[i] = i;
} }
} }
""" """
fd, path = tempfile.mkstemp(suffix='.c', prefix='test_omp_') default_openmp = GCC_compiler.try_compile_tmp(
dummy_stdin = open(os.devnull) code=code,
try: tmp_prefix='test_omp_',
os.write(fd, code) flags=['-fopenmp'],
os.close(fd) try_run=False)
fd = None
proc = call_subprocess_Popen(['g++', '-fopenmp', path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=dummy_stdin.fileno())
proc.wait()
if proc.returncode != 0:
default_openmp = False
finally:
del dummy_stdin
# Ensure `fd` is closed before we remove the temporary file.
try:
if fd is not None:
os.close(fd)
finally:
os.remove(path)
except OSError, e:
return False
return default_openmp return default_openmp
def update_self_openmp(self): def update_self_openmp(self):
......
...@@ -3,14 +3,11 @@ ...@@ -3,14 +3,11 @@
There is no standard name or location for this header, so we just insert it There is no standard name or location for this header, so we just insert it
ourselves into the C code ourselves into the C code
""" """
import os
import tempfile
import textwrap import textwrap
import subprocess
import sys import sys
from theano import config from theano import config
from theano.misc.windows import call_subprocess_Popen from theano.gof.cmodule import GCC_compiler
def detect_macos_sdot_bug(): def detect_macos_sdot_bug():
...@@ -65,61 +62,19 @@ def detect_macos_sdot_bug(): ...@@ -65,61 +62,19 @@ def detect_macos_sdot_bug():
return 0; return 0;
} }
""") """)
try:
fd, path = tempfile.mkstemp(suffix='.c',
prefix='detect_macos_sdot_bug_')
exe_path = path[:-2]
dummy_stdin = open(os.devnull)
compilation_failed = False
try:
os.write(fd, test_code)
os.close(fd)
fd = None
proc = call_subprocess_Popen(
['g++', path, '-o', exe_path] + flags,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=dummy_stdin.fileno())
proc.wait()
if proc.returncode != 0:
# We were not able to compile
compilation_failed = True
else:
# Try to execute the program
try:
proc = call_subprocess_Popen([exe_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=dummy_stdin.fileno())
proc.wait()
detect_macos_sdot_bug.tested = True
if proc.returncode != 0:
# The bug is present
detect_macos_sdot_bug.present = True
else:
detect_macos_sdot_bug.present = False
finally:
os.remove(exe_path)
finally:
del dummy_stdin
try:
if fd is not None:
os.close(fd)
finally:
os.remove(path)
except OSError, e: compilation_ok, run_ok = GCC_compiler.try_compile_tmp(test_code,
compilation_failed = True tmp_prefix='detect_macos_sdot_bug_', flags=flags, try_run=True)
detect_macos_sdot_bug.tested = True
# If compilation failed, we consider there is a bug, # If compilation failed, we consider there is a bug,
# and the fix does not work # and the fix does not work
if compilation_failed: if not compilation_ok:
detect_macos_sdot_bug.tested = True
detect_macos_sdot_bug.present = True detect_macos_sdot_bug.present = True
return True return True
if not detect_macos_sdot_bug.present: if run_ok:
detect_macos_sdot_bug.present = False
return False return False
# Else, try a simple fix # Else, try a simple fix
...@@ -145,56 +100,14 @@ def detect_macos_sdot_bug(): ...@@ -145,56 +100,14 @@ def detect_macos_sdot_bug():
return 0; return 0;
} }
""") """)
try:
fd, path = tempfile.mkstemp(suffix='.c', compilation_fix_ok, run_fix_ok = GCC_compiler.try_compile_tmp(
prefix='detect_macos_sdot_bug_testfix_') test_fix_code,
exe_path = path[:-2] tmp_prefix='detect_macos_sdot_bug_testfix_',
dummy_stdin = open(os.devnull) flags=flags,
compilation_failed = False try_run=True)
try:
os.write(fd, test_fix_code) detect_macos_sdot_bug.fix_works = run_fix_ok
os.close(fd)
fd = None
proc = call_subprocess_Popen(
['g++', path, '-o', exe_path] + flags,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=dummy_stdin.fileno())
proc.wait()
if proc.returncode != 0:
# We were not able to compile
compilation_failed = True
print >> sys.stderr, ("ERROR: Failed to compile tentative fix "
"for bug in BLAS shipped with Mac OS X")
print >> sys.stderr, "command line was:", ' '.join(
['g++', path, '-o', exe_path] + flags)
print >> sys.stderr, "error was:"
for l in proc.stderr:
print >> sys.stderr, l
else:
# Try to execute the program
try:
proc = call_subprocess_Popen([exe_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=dummy_stdin.fileno())
proc.wait()
if proc.returncode == 0:
# The fix is working
detect_macos_sdot_bug.fix_works = True
finally:
os.remove(exe_path)
finally:
del dummy_stdin
try:
if fd is not None:
os.close(fd)
finally:
os.remove(path)
except OSError, e:
compilation_failed = True
return detect_macos_sdot_bug.present return detect_macos_sdot_bug.present
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论