Check that `name_expressions` is iterable

情到浓时终转凉″ 提交于 2021-01-07 06:53:28

问题


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 kernel func1<T> and non-template kernel func2. Strings in this tuple must then be passed, one at a time, to get_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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!