问题
When trying out the new jitify
support planned for CuPy v9.x, I found that the name_expressions
named argument to cupy.RawModule
needs to be iterable for the NVRTC to not fail when later calling get_function
. Question stemming out of cupy.RawModule using name_expressions and nvcc and/or path.
def mykernel():
grid = (...)
blocks = (...)
args = (...)
with open('my_cuda_cpp_code.cu') as f:
code = f.read()
kers = ('nameofkernel')
mod = cp.RawModule(code=code, jitify=True, name_expressions=kers, ...)
mod.get_function('nameofkernel')(grid, block, args)
The code above produces the following error output:
Traceback (most recent call last):
File "/home/mikaeltw/env/lib/python3.8/site-packages/cupy/cuda/compiler.py", line 586, in compile
nvrtc.compileProgram(self.ptr, options)
File "cupy_backends/cuda/libs/nvrtc.pyx", line 108, in cupy_backends.cuda.libs.nvrtc.compileProgram
File "cupy_backends/cuda/libs/nvrtc.pyx", line 120, in cupy_backends.cuda.libs.nvrtc.compileProgram
File "cupy_backends/cuda/libs/nvrtc.pyx", line 58, in cupy_backends.cuda.libs.nvrtc.check_status
cupy_backends.cuda.libs.nvrtc.NVRTCError: NVRTC_ERROR_COMPILATION (6)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "./jitify_test.py", line 62, in <module>
test_mykernel()
File "./jitify_test.py", line 57, in test_mykernel
mykernel(x_out, x_in)
File "./jitify_test.py", line 50, in mykernel
mod.get_function('nameofkernel')(grid, block, args)
File "cupy/core/raw.pyx", line 470, in cupy.core.raw.RawModule.get_function
File "cupy/core/raw.pyx", line 394, in cupy.core.raw.RawModule.module.__get__
File "cupy/core/raw.pyx", line 402, in cupy.core.raw.RawModule._module
File "cupy/_util.pyx", line 53, in cupy._util.memoize.decorator.ret
File "cupy/core/raw.pyx", line 547, in cupy.core.raw._get_raw_module
File "cupy/core/core.pyx", line 1829, in cupy.core.core.compile_with_cache
File "cupy/core/core.pyx", line 1883, in cupy.core.core.compile_with_cache
File "/home/mikaeltw/env/lib/python3.8/site-packages/cupy/cuda/compiler.py", line 393, in compile_with_cache
return _compile_with_cache_cuda(
File "/home/mikaeltw/env/lib/python3.8/site-packages/cupy/cuda/compiler.py", line 472, in _compile_with_cache_cuda
ptx, mapping = compile_using_nvrtc(
File "/home/mikaeltw/env/lib/python3.8/site-packages/cupy/cuda/compiler.py", line 229, in compile_using_nvrtc
return _compile(source, options, cu_path,
File "/home/mikaeltw/env/lib/python3.8/site-packages/cupy/cuda/compiler.py", line 213, in _compile
ptx, mapping = prog.compile(options, log_stream)
File "/home/mikaeltw/env/lib/python3.8/site-packages/cupy/cuda/compiler.py", line 597, in compile
raise CompileException(log, self.src, self.name, options,
cupy.cuda.compiler.CompileException: __nv_name_map(2): error: expected an expression
__nv_name_map(2): error: Error in parsing name expression for lowered name lookup. Input name expression was: " :"
__nv_name_map(3): error: identifier "_" is undefined
--||--
Setting kers
to an iterable, e.g. ['nameofkernel']
or ('nameofkernel',)
and it works.
According to the docs https://docs.cupy.dev/en/stable/reference/generated/cupy.RawModule.html, the name_expressions
should be given as a sequence of strings. My suggestion is to check that name_expressions
is iterable (not just a single str, even though str is iterable), to catch an otherwise cryptic error when calling get_function
.
回答1:
Well, first of all, we did say it's a sequence (ex: list/tuple) of strings and gave an example in the doc page you quoted:
name_expressions
(sequence of str) – A sequence (e.g. list) of strings referring to the names of C++ global/template kernels. For example,name_expressions=['func1<int>', 'func1<double>', 'func2']
for the template kernelfunc1<T>
and non-template kernelfunc2
. Strings in this tuple must then be passed, one at a time, toget_function()
to retrieve the corresponding kernel.
So I don't see any ambiguity. There is no doubt that it's such a common pitfall in Python to write ('abc')
and thinking it's a 1-element tuple containing the string 'abc'
, for which it should been written as ('abc',)
with comma. But checking for such pitfall everywhere in the codebase would be a pain in the ass IMHO.
Second, even if we add a check to ensure the input is iterable, it still doesn't solve your issue as strings are also iterable/sequence:
>>> import collections.abc
>>> isinstance((1,2), collections.abc.Iterable)
True
>>> isinstance((1,2), collections.abc.Sequence)
True
>>> isinstance('abc', collections.abc.Iterable)
True
>>> isinstance('abc', collections.abc.Sequence)
True
So there is no good way to enforce this check other than checking it explicitly via isinstance(name_expressions, str)
, which circles back to the pain I mentioned above.
来源:https://stackoverflow.com/questions/65087601/check-that-name-expressions-is-iterable