onnxruntime我正在构建一个在底层使用的库(Ubuntu 22) 。反过来,onnxruntime使用 CUDA,动态加载一些专用的“后端”。我构建了除 CUDA 库之外的整个代码堆栈,并且没有一个库具有其RPATH或RUNPATH设置(使用 进行双重检查readelf -d)。
我构建了两个应用程序,一个是 C++,并直接链接到我的库。该应用程序有其RPATH设置,一切正常。如果我运行它,LD_DEBUG=libs我会看到类似这样的内容(请注意,路径已被编辑,并且我仅显示调试输出的一小部分):
158834: calling init: .../install/bin/../lib/libonnxruntime_providers_cuda.so
158834:
158834: find library=libcudnn_ops_infer.so.8 [0]; searching
158834: search path=.../install/bin/../lib (RPATH from file .../install/bin/test)
158834: trying file=.../install/bin/../lib/libcudnn_ops_infer.so.8
158834:
158834:
158834: calling init: .../install/bin/../lib/libcudnn_ops_infer.so.8
158834:
Run Code Online (Sandbox Code Playgroud)
这就是我所期待的,我很高兴。
但是,我还需要通过一些链接到它的 python 绑定来使用相同的库。为了让它工作,我需要在这种情况下设置RPATHpython 绑定(至少在我看来,它只是一个在运行时加载的共享库)。请注意,Python 可执行文件既没有RPATH也没有RUNPATH设置。这仅部分有效。也就是说,RPATH传播似乎在沿着依赖关系树向下移动时起作用,直到开始搜索 CUDA 库,此时它不再起作用。这是以相同的方式、相同的构建运行完全相同的 onnxruntime API,并在与上面相同的文件夹中使用相同的文件。唯一的区别是 python 扩展层。输出LD_DEBUG如下所示:
159602: find library=libonnxruntime.so.1.15.1 [0]; searching
159602: search path=.../install/lib/../lib …Run Code Online (Sandbox Code Playgroud) 我正在努力使用 Cython 正确并行化函数。基本上,问题是对一些数据进行分类。实际代码有点长,但最终它做了这样的事情:
def bin_var(double[:] dist,
double[:] values,
double[:] bin_def,
double[:] varg, long[:] count):
dbin = (bin_def[1] - bin_def[0]) / bin_def[2]
for n1 in range(values.size):
if (dist[n1] < bin_def[0]) or (dist[n1] >= bin_def[1]):
continue
else:
ni = int((dist - bin_def[0]) / dbin)
count[ni] += 1
varg[ni] += calc_something(values[ni])
# Compute the mean
for n1 in range(int(bin_def[2])):
varg[ni] /= count[ni]
Run Code Online (Sandbox Code Playgroud)
该代码适合一些简单的并行化(values并且dist非常大):需要将第一个for循环拆分为单独的进程,每个进程都处理自己版本的count和varg数组。完成后,必须通过对第二个for循环(更短)之前的count和的不同版本求和来将所有内容组合在一起。varg
也就是说,我花了两天时间试图了解如何在 Cython 中有效地实现这一点,并且我开始怀疑当前版本的语言是不可能的。请注意,仅在第一个循环中使用prangefrom …
multithreading multiprocessing cython python-multiprocessing
我刚刚注意到 pyhton 中 Enum+defaultdict 的一个非常奇怪的行为。我定义了一个这样的枚举,它收集一些默认字典:
from enum import Enum
from collections import defaultdict
class A(Enum):
a = defaultdict(lambda: 1)
b = defaultdict(lambda: 2)
Run Code Online (Sandbox Code Playgroud)
然后,当我查看 A 里面的内容时:
In [11]: A.a
Out[11]: <A.a: defaultdict(<function A.<lambda> at 0x7f773f03b510>, {})>
In [12]: A.b
Out[12]: <A.a: defaultdict(<function A.<lambda> at 0x7f773f03b510>, {})>
Run Code Online (Sandbox Code Playgroud)
SoA.b只是 的别名A.a。对我来说,这看起来很像一个错误,即使背后可能有一些充分的理由。任何想法?
附录
由于它出现在评论中,因此需要说明为什么要在枚举中放入字典。我发现将常量分组到命名空间中通常很有用,这样就可以访问A.a.constant1、A.b.constant1等值。目前,尝试使用 Enums 执行此操作会引发AttributeError. 当然,人们可以这样做:
class A:
class a(Enum):
constant1 = 1
class b(Enum):
constant1 = 2
Run Code Online (Sandbox Code Playgroud)
然而,这并没有利用 Enum 的功能(迭代、访问__getitem__等)。