检查 `name_expressions` 是否可迭代
Check that `name_expressions` is iterable
在尝试为 CuPy v9.x 计划的新 jitify
支持时,我发现 cupy.RawModule
的 name_expressions
命名参数需要是可迭代的,以便 NVRTC稍后调用 get_function
时不会失败。来自 .
的问题
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)
上面的代码产生以下错误输出:
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
--||--
将 kers
设置为可迭代对象,例如['nameofkernel']
或 ('nameofkernel',)
并且有效。
根据文档 https://docs.cupy.dev/en/stable/reference/generated/cupy.RawModule.html,name_expressions
应该作为字符串序列给出。我的建议是检查 name_expressions
是可迭代的(不仅仅是一个 str,即使 str 是可迭代的),以在调用 get_function
.
时捕获一个神秘的错误
好吧,首先,我们确实说过它是字符串的 序列 (例如:list/tuple),并在您引用的文档页面中给出了一个示例:
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.
所以我看不出有任何歧义。毫无疑问,在 Python 中写 ('abc')
并认为它是一个包含字符串 'abc'
的 1 元素元组是一个常见的陷阱,为此它应该写成 [=18] =] 带逗号。但是,恕我直言,在代码库中到处检查这样的陷阱将是一件很痛苦的事。
其次,即使我们添加检查以确保输入是可迭代的,它仍然不能解决您的问题,因为字符串也是 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
因此,除了通过 isinstance(name_expressions, str)
明确检查之外,没有其他好的方法来执行此检查,这又回到了我上面提到的痛苦。
在尝试为 CuPy v9.x 计划的新 jitify
支持时,我发现 cupy.RawModule
的 name_expressions
命名参数需要是可迭代的,以便 NVRTC稍后调用 get_function
时不会失败。来自
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)
上面的代码产生以下错误输出:
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
--||--
将 kers
设置为可迭代对象,例如['nameofkernel']
或 ('nameofkernel',)
并且有效。
根据文档 https://docs.cupy.dev/en/stable/reference/generated/cupy.RawModule.html,name_expressions
应该作为字符串序列给出。我的建议是检查 name_expressions
是可迭代的(不仅仅是一个 str,即使 str 是可迭代的),以在调用 get_function
.
好吧,首先,我们确实说过它是字符串的 序列 (例如:list/tuple),并在您引用的文档页面中给出了一个示例:
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.
所以我看不出有任何歧义。毫无疑问,在 Python 中写 ('abc')
并认为它是一个包含字符串 'abc'
的 1 元素元组是一个常见的陷阱,为此它应该写成 [=18] =] 带逗号。但是,恕我直言,在代码库中到处检查这样的陷阱将是一件很痛苦的事。
其次,即使我们添加检查以确保输入是可迭代的,它仍然不能解决您的问题,因为字符串也是 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
因此,除了通过 isinstance(name_expressions, str)
明确检查之外,没有其他好的方法来执行此检查,这又回到了我上面提到的痛苦。