|
17 | 17 | import site
|
18 | 18 | import sys
|
19 | 19 | import os
|
| 20 | +import warnings |
| 21 | +import platform |
20 | 22 |
|
21 | 23 | core_suffix = 'so'
|
22 | 24 | if os.name == 'nt':
|
@@ -62,7 +64,6 @@ def avx_supported():
|
62 | 64 | """
|
63 | 65 | Whether current system(Linux, MacOS, Windows) is supported with AVX.
|
64 | 66 | """
|
65 |
| - import platform |
66 | 67 | from .. import compat as cpt
|
67 | 68 | sysstr = platform.system().lower()
|
68 | 69 | has_avx = False
|
@@ -160,6 +161,72 @@ def asm_func(code_str, restype=ctypes.c_uint32, argtypes=()):
|
160 | 161 | return False
|
161 | 162 |
|
162 | 163 |
|
| 164 | +def run_shell_command(cmd): |
| 165 | + import subprocess |
| 166 | + out, err = subprocess.Popen( |
| 167 | + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, |
| 168 | + shell=True).communicate() |
| 169 | + if err: |
| 170 | + return None |
| 171 | + else: |
| 172 | + return out.decode('utf-8') |
| 173 | + |
| 174 | + |
| 175 | +def get_dso_path(core_so, dso_name): |
| 176 | + if core_so and dso_name: |
| 177 | + return run_shell_command("ldd %s|grep %s|awk '{print $3}'" % |
| 178 | + (core_so, dso_name)).strip() |
| 179 | + else: |
| 180 | + return None |
| 181 | + |
| 182 | + |
| 183 | +def load_dso(dso_absolute_path): |
| 184 | + if dso_absolute_path: |
| 185 | + try: |
| 186 | + from ctypes import cdll |
| 187 | + cdll.LoadLibrary(dso_absolute_path) |
| 188 | + except: |
| 189 | + warnings.warn("Load {} failed".format(dso_absolute_path)) |
| 190 | + |
| 191 | + |
| 192 | +def pre_load(dso_name): |
| 193 | + if has_avx_core: |
| 194 | + core_so = current_path + os.sep + 'core_avx.' + core_suffix |
| 195 | + elif has_noavx_core: |
| 196 | + core_so = current_path + os.sep + 'core_noavx.' + core_suffix |
| 197 | + else: |
| 198 | + core_so = None |
| 199 | + dso_path = get_dso_path(core_so, dso_name) |
| 200 | + load_dso(dso_path) |
| 201 | + |
| 202 | + |
| 203 | +def get_glibc_ver(): |
| 204 | + return run_shell_command("ldd --version | awk '/ldd/{print $NF}'").strip() |
| 205 | + |
| 206 | + |
| 207 | +def less_than_ver(a, b): |
| 208 | + import re |
| 209 | + import operator |
| 210 | + |
| 211 | + def to_list(s): |
| 212 | + s = re.sub('(\.0+)+$', '', s) |
| 213 | + return [int(x) for x in s.split('.')] |
| 214 | + |
| 215 | + return operator.lt(to_list(a), to_list(b)) |
| 216 | + |
| 217 | + |
| 218 | +# NOTE(zhiqiu): An error may occurs when import paddle in linux platform with glibc < 2.22, |
| 219 | +# the error message of which is "dlopen: cannot load any more object with static TLS". |
| 220 | +# This happens when: |
| 221 | +# (1) the number of dynamic shared librarys (DSO) loaded > 14, |
| 222 | +# (2) after that, load a dynamic shared library (DSO) with static TLS. |
| 223 | +# For paddle, the problem is that 'libgomp' is a DSO with static TLS, and it is loaded after 14 DSOs. |
| 224 | +# So, here is a tricky way to solve the problem by pre load 'libgomp' before 'core_avx.so'. |
| 225 | +# The final solution is to upgrade glibc to > 2.22 on the target system. |
| 226 | +if platform.system().lower() == 'linux' and less_than_ver(get_glibc_ver(), |
| 227 | + '2.23'): |
| 228 | + pre_load('libgomp') |
| 229 | + |
163 | 230 | load_noavx = False
|
164 | 231 |
|
165 | 232 | if avx_supported():
|
|
0 commit comments