提交 ef158c39 authored 作者: nouiz's avatar nouiz

Merge pull request #1301 from lamblin/unique_fct_names

Compute hash on whole source file
......@@ -4,7 +4,6 @@ Defines Linkers that deal with C implementations.
# Python imports
from copy import copy
import re # for set_compiledir
import os
import StringIO
import sys
......@@ -589,7 +588,14 @@ class CLinker(link.Linker):
## ivnames + ovnames):
## sub[vname] = symbol[variable]
name = "node_%i" % node_num
# The placeholder will be replaced by a hash of the entire
# code (module + support code) in DynamicModule.code.
# This ensures that, when defining functions in support code,
# we cannot have two different functions, in different modules,
# that have the same name.
# It was problematic, in particular, on Mac OS X (10.6 and 10.7)
# when defining CUDA kernels (with Cuda 4.2 and 5.0). See gh-1172.
name = "node_<<<<HASH_PLACEHOLDER>>>>_%i" % node_num
isyms = [symbol[r] for r in node.inputs]
osyms = [symbol[r] for r in node.outputs]
......@@ -643,24 +649,15 @@ class CLinker(link.Linker):
args += ["storage_%s" % symbol[variable] for variable
in utils.uniq(self.inputs + self.outputs + self.orphans)]
# <<<<HASH_PLACEHOLDER>>>> will be replaced by a hash of the whole
# code in the file, including support code, in DynamicModule.code.
struct_name = '__struct_compiled_op_%s' % '<<<<HASH_PLACEHOLDER>>>>'
struct_code = struct_gen(args, init_blocks, blocks,
dict(failure_var=failure_var,
name="<<<<NAME>>>>"))
# TODO: still needed? We do not use weave anymore.
# The hash calculated on the code identifies it so weave can
# cache properly. (the hash has to be used outside of the
# support code because weave does not consider changes in the
# support code)
hash = hash_from_code(struct_code)
struct_name = '__struct_compiled_op_%s' % hash
#struct_code %= dict(name = struct_name)
struct_code = re.sub("<<<<NAME>>>>", struct_name, struct_code)
name=struct_name))
self.struct_code = struct_code
self.struct_name = struct_name
self.hash = hash
self.args = args
self.r2symbol = symbol
self.init_blocks = init_blocks
......@@ -1204,7 +1201,7 @@ class CLinker(link.Linker):
_logger.debug("LOCATION %s", str(location))
try:
module = c_compiler.compile_str(
module_name=mod.name,
module_name=mod.code_hash,
src_code=src_code,
location=location,
include_dirs=self.header_dirs(),
......@@ -1224,9 +1221,8 @@ class CLinker(link.Linker):
for our fgraph.
"""
self.code_gen()
module_name = self.hash
mod = cmodule.DynamicModule(module_name)
mod = cmodule.DynamicModule()
# The code of instantiate
# the 1 is for error_storage
......
......@@ -5,6 +5,7 @@ import cPickle
import logging
import operator
import os
import re
import shutil
import stat
import StringIO
......@@ -121,8 +122,18 @@ class ExtFunction(object):
class DynamicModule(object):
def __init__(self, name):
self.name = name
def __init__(self, name=None):
assert name is None, ("The 'name' parameter of DynamicModule"
" cannot be specified anymore. Instead, 'code_hash'"
" will be automatically computed and can be used as"
" the module's name.")
# While the module is not finalized, we can call add_...
# when it is finalized, a hash is computed and used instead of
# the placeholder, and as module name.
self.finalized = False
self.code_hash = None
self.hash_placeholder = '<<<<HASH_PLACEHOLDER>>>>'
self.support_code = []
self.functions = []
self.includes = ["<Python.h>", "<iostream>"]
......@@ -150,31 +161,35 @@ static struct PyModuleDef moduledef = {{
-1,
MyMethods,
}};
""".format(name=self.name)
print >> stream, "PyMODINIT_FUNC PyInit_%s(void) {" % self.name
""".format(name=self.hash_placeholder)
print >> stream, "PyMODINIT_FUNC PyInit_%s(void) {" % self.hash_placeholder
for block in self.init_blocks:
print >> stream, ' ', block
print >> stream, " PyObject *m = PyModule_Create(&moduledef);"
print >> stream, " return m;"
else:
print >> stream, "PyMODINIT_FUNC init%s(void){" % self.name
print >> stream, "PyMODINIT_FUNC init%s(void){" % self.hash_placeholder
for block in self.init_blocks:
print >> stream, ' ', block
print >> stream, ' ', ('(void) Py_InitModule("%s", MyMethods);'
% self.name)
% self.hash_placeholder)
print >> stream, "}"
def add_include(self, str):
assert not self.finalized
self.includes.append(str)
def add_init_code(self, code):
assert not self.finalized
self.init_blocks.append(code)
def add_support_code(self, code):
assert not self.finalized
if code not in self.support_code: # TODO: KLUDGE
self.support_code.append(code)
def add_function(self, fn):
assert not self.finalized
self.functions.append(fn)
def code(self):
......@@ -205,7 +220,14 @@ static struct PyModuleDef moduledef = {{
self.print_methoddef(sio)
self.print_init(sio)
return sio.getvalue()
rval = sio.getvalue()
self.code_hash = hash_from_code(rval)
rval = re.sub(self.hash_placeholder, self.code_hash, rval)
# Finalize the Module, so no support code or function
# can be added
self.finalized = True
return rval
def list_code(self, ofile=sys.stdout):
"""Print out the code with line numbers to `ofile` """
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论