intel-extension-for-pytorch

Форк
0
1240 строк · 40.2 Кб
1
# This Python file uses the following encoding: utf-8
2
# !/usr/bin/env python
3

4
# Welcome to the Intel Extension for PyTorch setup.py.
5
#
6
# Environment variables you are probably interested in:
7
#
8
#   DEBUG
9
#     build with -O0 and -g (debug symbols)
10
#
11
#   RELEASE
12
#     build with optimization level -O2
13
#
14
#   REL_WITH_DEB_INFO
15
#     build with optimization level -O2 and -g (debug symbols)
16
#
17
#   CFLAGS
18
#     flags to apply to both C and C++ files to be compiled (a quirk of setup.py
19
#     which we have faithfully adhered to in our build system is that CFLAGS
20
#     also applies to C++ files (unless CXXFLAGS is set), in contrast to the
21
#     default behavior of autogoo and cmake build systems.)
22
#
23
#   CC
24
#     the C/C++ compiler to use
25
#
26
#   MKLROOT
27
#     specify MKL library path.
28
#     ONLY NEEDED if you have a specific MKL version you want to link against.
29
#     Make sure this directory contains include and lib directories.
30
#     By default, the MKL library installed with pip/conda is used.
31
#
32
# Environment variables we respect (these environment variables are
33
# conventional and are often understood/set by other software.)
34
#
35
#   TORCH_VERSION
36
#     specify the PyTorch version to depend on
37
#
38
#   IPEX_VERSION
39
#     specify the extension version literal
40
#
41
#   MAX_JOBS
42
#     process for parallel compile, must be a Integer
43
#
44
#   VERBOSE
45
#     more output when compile
46
#
47
#   IPEX_VERSIONED_BUILD
48
#     build wheel files versioned with a git commit number
49
#
50

51
##############################################################
52
# XPU Build options:
53
# USE_ONEMKL            - to use oneMKL in operators
54
# USE_CHANNELS_LAST_1D  - to use channels last 1d feature
55
# USE_PERSIST_STREAM    - to use persistent oneDNN stream
56
# USE_PRIMITIVE_CACHE   - to Cache oneDNN primitives by framework
57
# USE_QUEUE_BARRIER     - to use queue submit_barrier API
58
# USE_SCRATCHPAD_MODE   - to trun on oneDNN scratchpad user mode
59
# USE_MULTI_CONTEXT     - to create DPC++ runtime context per device
60
# USE_AOT_DEVLIST       - to set device list for AOT build option, for example, bdw,tgl,ats,..."
61
# USE_SYCL_ASSERT       - to enable assert in sycl kernel
62
# USE_ITT_ANNOTATION    - to enable ITT annotation in sycl kernel
63
# BUILD_STATIC_ONEMKL   - to link static oneMKL libraries
64
# BUILD_STATS           - to count statistics for each component during build process
65
# BUILD_BY_PER_KERNEL   - to build by DPC++ per_kernel option (exclusive with USE_AOT_DEVLIST)
66
# BUILD_STRIPPED_BIN    - to strip all symbols after build
67
# BUILD_SEPARATE_OPS    - to build each operator in separate library
68
# BUILD_SIMPLE_TRACE    - to build simple trace for each registered operator
69
# BUILD_OPT_LEVEL       - to add build option -Ox, accept values: 0/1
70
# BUILD_NO_CLANGFORMAT  - to build without force clang-format
71
# BUILD_INTERNAL_DEBUG  - to build internal debug code path
72
#
73
##############################################################
74

75
from __future__ import print_function
76
from distutils.command.build_py import build_py
77
from distutils.command.install import install
78
from distutils.version import LooseVersion
79
from functools import lru_cache
80
from subprocess import check_call, check_output
81
from setuptools.command.build_clib import build_clib
82
from setuptools.command.egg_info import egg_info
83
from setuptools import setup, distutils
84
from pathlib import Path
85
from typing import Any, Optional
86

87
import sysconfig
88
import distutils.ccompiler
89
import distutils.command.clean
90
import os
91
import glob
92
import platform
93
import shutil
94
import subprocess
95
import sys
96
import errno
97

98

99
# FIXME: always set BUILD_WITH_XPU = ON in XPU repo
100
os.environ["BUILD_WITH_XPU"] = "OFF"
101

102

103
# Define env values
104
ON_ENV_VAL = ["ON", "YES", "1", "Y"]
105
OFF_ENV_VAL = ["OFF", "NO", "0", "N"]
106
FULL_ENV_VAL = ON_ENV_VAL + OFF_ENV_VAL
107

108

109
# initialize variables for compilation
110
IS_LINUX = platform.system() == "Linux"
111
IS_DARWIN = platform.system() == "Darwin"
112
IS_WINDOWS = platform.system() == "Windows"
113

114

115
@lru_cache(maxsize=128)
116
def _get_build_target():
117
    build_target = ""
118
    if len(sys.argv) > 1:
119
        if sys.argv[1] in ["build_clib", "bdist_cppsdk"]:
120
            build_target = "cppsdk"
121
        elif sys.argv[1] in ["clean"]:
122
            build_target = "clean"
123
        elif sys.argv[1] in ["develop"]:
124
            build_target = "develop"
125
        else:
126
            build_target = "python"
127
    return build_target
128

129

130
torch_install_prefix = None
131
if _get_build_target() == "cppsdk":
132
    torch_install_prefix = os.environ.get("LIBTORCH_PATH", None)
133
    if torch_install_prefix is None or not os.path.exists(torch_install_prefix):
134
        raise RuntimeError("Can not find libtorch from env LIBTORCH_PATH!")
135
    torch_install_prefix = os.path.abspath(torch_install_prefix)
136
elif _get_build_target() in ["develop", "python"]:
137
    try:
138
        import torch
139
        from torch.utils.cpp_extension import BuildExtension, CppExtension
140
    except ImportError as e:
141
        raise RuntimeError("Fail to import torch!")
142

143

144
def _check_env_flag(name, default=""):
145
    return os.getenv(name, default).upper() in ON_ENV_VAL
146

147

148
def get_build_type():
149
    return (
150
        "RelWithDebInfo"
151
        if _check_env_flag("REL_WITH_DEB_INFO")
152
        else "Debug"
153
        if _check_env_flag("DEBUG")
154
        else "Release"
155
    )
156

157

158
def create_if_not_exist(path_dir):
159
    if not os.path.exists(path_dir):
160
        try:
161
            Path(path_dir).mkdir(parents=True, exist_ok=True)
162
        except OSError as exc:  # Guard against race condition
163
            if exc.errno != errno.EEXIST:
164
                raise RuntimeError("Fail to create path {}".format(path_dir))
165

166

167
def get_version_num():
168
    versions = {}
169
    version_file = "version.txt"
170
    version_lines = open(version_file, "r").readlines()
171
    for line in version_lines:
172
        key, value = line.strip().split(" ")
173
        versions[key] = value
174
    for v in ("VERSION_MAJOR", "VERSION_MINOR", "VERSION_PATCH"):
175
        if v not in versions:
176
            print("ERROR:", v, "is not found in", version_file)
177
            sys.exit(1)
178
    version = (
179
        versions["VERSION_MAJOR"]
180
        + "."
181
        + versions["VERSION_MINOR"]
182
        + "."
183
        + versions["VERSION_PATCH"]
184
    )
185
    return version
186

187

188
PACKAGE_NAME = "intel_extension_for_pytorch"
189
PYTHON_VERSION = sys.version_info
190

191

192
def get_pytorch_install_dir():
193
    if _get_build_target() == "clean":
194
        return None
195
    if _get_build_target() == "cppsdk":
196
        return torch_install_prefix
197
    else:
198
        return os.path.dirname(os.path.abspath(torch.__file__))
199

200

201
pytorch_install_dir = get_pytorch_install_dir()
202

203

204
def _build_installation_dependency():
205
    install_requires = []
206
    install_requires.append("psutil")
207
    install_requires.append("numpy")
208
    install_requires.append("packaging")
209
    return install_requires
210

211

212
def which(thefile: str) -> Optional[str]:
213
    path = os.environ.get("PATH", os.defpath).split(os.pathsep)
214
    for d in path:
215
        fname = os.path.join(d, thefile)
216
        fnames = [fname]
217
        if sys.platform == "win32":
218
            exts = os.environ.get("PATHEXT", "").split(os.pathsep)
219
            fnames += [fname + ext for ext in exts]
220
        for name in fnames:
221
            if os.access(name, os.F_OK | os.X_OK) and not os.path.isdir(name):
222
                return name
223
    return None
224

225

226
def get_cmake_command():
227
    if IS_WINDOWS:
228
        return "cmake"
229

230
    def _get_version(cmd: Optional[str]) -> Any:
231
        "Returns cmake version."
232
        if cmd is None:
233
            return None
234
        for line in check_output([cmd, "--version"]).decode("utf-8").split("\n"):
235
            if "version" in line:
236
                return LooseVersion(line.strip().split(" ")[2])
237
        raise RuntimeError("no version found")
238

239
    cmake3_version = _get_version(which("cmake3"))
240
    cmake_version = _get_version(which("cmake"))
241

242
    _cmake_min_version = LooseVersion("3.13.0")
243
    if all(
244
        (
245
            ver is None or ver < _cmake_min_version
246
            for ver in [cmake_version, cmake3_version]
247
        )
248
    ):
249
        raise RuntimeError("Require cmake or cmake3 3.13.0 or higher but not found")
250

251
    if cmake3_version is None:
252
        cmake_command = "cmake"
253
    elif cmake_version is None:
254
        cmake_command = "cmake3"
255
    else:
256
        if cmake3_version >= cmake_version:
257
            cmake_command = "cmake3"
258
        else:
259
            cmake_command = "cmake"
260
    return cmake_command
261

262

263
def get_cpack_command():
264
    if IS_WINDOWS:
265
        return "cpack"
266
    if shutil.which("cpack3") is not None:
267
        return "cpack3"
268
    if shutil.which("cpack") is not None:
269
        return "cpack"
270
    else:
271
        raise RuntimeError("no cpack or cpack3 found")
272

273

274
def get_ipex_git_head_sha(base_dir):
275
    ipex_git_sha = (
276
        subprocess.check_output(["git", "rev-parse", "--short", "HEAD"], cwd=base_dir)
277
        .decode("ascii")
278
        .strip()
279
    )
280
    return ipex_git_sha
281

282

283
def get_torch_git_head_sha():
284
    if _get_build_target() == "clean":
285
        return None
286
    if _get_build_target() == "cppsdk":
287
        libtorch_hash_file = os.path.join(torch_install_prefix, "build-hash")
288
        if not os.path.exists(libtorch_hash_file):
289
            raise RuntimeError(
290
                "can not find build-hash at {}".format(libtorch_hash_file)
291
            )
292
        with open(libtorch_hash_file, "r") as f:
293
            lines = f.readlines()
294
            for line in lines:
295
                line = line.strip()
296
                if line.isalnum():
297
                    return line
298
        raise RuntimeError("can not get libtorch hash in {}".format(libtorch_hash_file))
299
    else:
300
        torch_git_sha = torch.version.git_version
301
        return torch_git_sha
302

303

304
def get_submodule_commit(base_dir, submodule_dir):
305
    if not os.path.isdir(submodule_dir):
306
        return ""
307
    return (
308
        subprocess.check_output(
309
            ["git", "submodule", "status", submodule_dir], cwd=base_dir
310
        )
311
        .decode("ascii")
312
        .strip()
313
        .split()[0]
314
    )
315

316

317
def get_build_version(ipex_git_sha):
318
    ipex_version = os.getenv("IPEX_VERSION", get_version_num())
319
    if "IPEX_VERSION" not in os.environ:
320
        if _check_env_flag("IPEX_VERSIONED_BUILD", default="1"):
321
            try:
322
                ipex_version += "+git" + ipex_git_sha[:7]
323
            except Exception:
324
                pass
325
        else:
326
            pkg_type = "xpu" if _check_env_flag("BUILD_WITH_XPU") else "cpu"
327
            ipex_version += "+" + pkg_type
328
    return ipex_version
329

330

331
def write_buffer_to_file(file_path, buffer):
332
    create_if_not_exist(os.path.dirname(file_path))
333
    with open(file_path, "w") as f:
334
        f.write(buffer)
335
        f.close()
336

337

338
def get_code_fingerprint(ipex_build_version, ipex_git_sha, torch_git_sha, build_type):
339
    fingerprint = "{}_{}_{}_{}".format(
340
        ipex_build_version, ipex_git_sha, torch_git_sha, build_type
341
    )
342
    return fingerprint
343

344

345
def check_code_fingerprint_in_file(file_path, fingerprint):
346
    b_exist = os.path.isfile(file_path)
347
    if b_exist is False:
348
        return False
349

350
    with open(file_path) as file:
351
        # read all content of a file
352
        content = file.read()
353
        # check if string present in a file
354
        if fingerprint in content:
355
            return True
356
        else:
357
            return False
358

359

360
def create_version_files(
361
    base_dir,
362
    ipex_build_version,
363
    ipex_git_sha,
364
    torch_git_sha,
365
    gpu_onednn_sha,
366
    cpu_ideep_sha,
367
):
368
    print(
369
        "Building Intel Extension for PyTorch. Version: {}".format(ipex_build_version)
370
    )
371
    py_version_path = os.path.join(base_dir, PACKAGE_NAME, "_version.py")
372
    cpp_version_path = os.path.join(
373
        base_dir, PACKAGE_NAME, "..", "csrc", "utils", "version.h"
374
    )
375
    build_type_str = get_build_type()
376
    # Check code fingerprint to avoid non-modify rebuild.
377
    current_code_fingerprint = get_code_fingerprint(
378
        ipex_build_version, ipex_git_sha, torch_git_sha, build_type_str
379
    )
380

381
    b_same_fingerprint = check_code_fingerprint_in_file(
382
        py_version_path, current_code_fingerprint
383
    )
384
    if b_same_fingerprint is False:
385
        py_buffer = "# Autogenerated file, do not edit!\n"
386
        py_buffer += "# code fingerprint:\n"
387
        py_buffer += "# {}\n\n".format(current_code_fingerprint)
388
        py_buffer += '__version__ = "{}"\n'.format(ipex_build_version)
389
        py_buffer += '__ipex_gitrev__ = "{}"\n'.format(ipex_git_sha)
390
        py_buffer += '__torch_gitrev__ = "{}"\n'.format(
391
            "" if build_type_str == "Release" else torch_git_sha
392
        )
393
        py_buffer += '__gpu_onednn_gitrev__ = "{}"\n'.format(gpu_onednn_sha)
394
        py_buffer += '__cpu_ideep_gitrev__ = "{}"\n'.format(cpu_ideep_sha)
395
        py_buffer += '__build_type__ = "{}"\n'.format(build_type_str)
396

397
        write_buffer_to_file(py_version_path, py_buffer)
398

399
    b_same_fingerprint = check_code_fingerprint_in_file(
400
        cpp_version_path, current_code_fingerprint
401
    )
402
    if b_same_fingerprint is False:
403
        c_buffer = "// Autogenerated file, do not edit!\n"
404
        c_buffer += "// clang-format off\n"
405
        c_buffer += "// code fingerprint: {}\n".format(current_code_fingerprint)
406
        c_buffer += "// clang-format on\n\n"
407
        c_buffer += "#pragma once\n"
408
        c_buffer += "#include <string>\n\n"
409
        c_buffer += "namespace torch_ipex {\n\n"
410
        c_buffer += "const std::string __version__()\n"
411
        c_buffer += '{{ return "{}"; }}\n\n'.format(ipex_build_version)
412
        c_buffer += "const std::string __gitrev__()\n"
413
        c_buffer += '{{ return "{}"; }}\n\n'.format(ipex_git_sha)
414
        c_buffer += "const std::string __torch_gitrev__()\n"
415
        c_buffer += '{{ return "{}"; }}\n\n'.format(torch_git_sha)
416
        c_buffer += "const std::string __build_type__()\n"
417
        c_buffer += '{{ return "{}"; }}\n\n'.format(build_type_str)
418
        c_buffer += "}  // namespace torch_ipex\n"
419

420
        write_buffer_to_file(cpp_version_path, c_buffer)
421

422

423
def get_project_dir():
424
    project_root_dir = os.path.dirname(__file__)
425
    return os.path.abspath(project_root_dir)
426

427

428
def get_build_dir():
429
    return os.path.join(get_project_dir(), "build")
430

431

432
def get_build_type_dir():
433
    build_type_dir = os.path.join(get_build_dir(), get_build_type())
434
    create_if_not_exist(build_type_dir)
435
    return build_type_dir
436

437

438
def get_package_base_dir():
439
    return os.path.join(get_build_type_dir(), "packages")
440

441

442
def get_package_dir():
443
    return os.path.join(get_package_base_dir(), PACKAGE_NAME)
444

445

446
def get_package_lib_dir():
447
    package_lib_dir = os.path.join(get_package_dir(), "lib")
448
    create_if_not_exist(package_lib_dir)
449
    return package_lib_dir
450

451

452
def get_ipex_cpu_dir():
453
    cpu_root_dir = os.path.join(get_project_dir(), "csrc", "cpu")
454
    return os.path.abspath(cpu_root_dir)
455

456

457
def get_ipex_cpu_build_dir():
458
    cpu_build_dir = os.path.join(get_build_type_dir(), "csrc", "cpu")
459
    create_if_not_exist(cpu_build_dir)
460
    return cpu_build_dir
461

462

463
def get_xpu_project_dir():
464
    project_root_dir = os.path.abspath(os.path.dirname(__file__))
465
    return os.path.join(project_root_dir)
466

467

468
def get_xpu_project_build_dir():
469
    xpu_build_dir = os.path.join(get_build_type_dir(), "csrc", "gpu")
470
    create_if_not_exist(xpu_build_dir)
471
    return xpu_build_dir
472

473

474
def get_xpu_compliers():
475
    if shutil.which("icx") is None or shutil.which("icpx") is None:
476
        raise RuntimeError("Failed to find compiler path from OS PATH")
477
    if IS_WINDOWS:
478
        return "icx", "icx"
479
    else:
480
        return "icx", "icpx"
481

482

483
def get_cpu_compliers():
484
    if shutil.which("icx") is None or shutil.which("icpx") is None:
485
        # For CPU build, Intel Compiler is optional.
486
        return None, None
487
    if IS_WINDOWS:
488
        return "icx", "icx"
489
    else:
490
        return "icx", "icpx"
491

492

493
def get_ipex_python_dir():
494
    project_root_dir = os.path.dirname(__file__)
495
    python_root_dir = os.path.join(project_root_dir, PACKAGE_NAME, "csrc")
496
    return os.path.abspath(python_root_dir)
497

498

499
def get_ipex_python_build_dir():
500
    python_build_dir = os.path.join(get_build_type_dir(), PACKAGE_NAME, "csrc")
501
    create_if_not_exist(python_build_dir)
502
    return python_build_dir
503

504

505
def get_ipex_cppsdk_build_dir():
506
    cppsdk_build_dir = os.path.join(get_build_type_dir(), "csrc", "cppsdk")
507
    create_if_not_exist(cppsdk_build_dir)
508
    return cppsdk_build_dir
509

510

511
base_dir = os.path.dirname(os.path.abspath(__file__))
512
# Generate version info (ipex.__version__)
513
torch_git_sha = get_torch_git_head_sha()
514
ipex_git_sha = get_ipex_git_head_sha(base_dir)
515
ipex_build_version = get_build_version(ipex_git_sha)
516
ipex_gpu_onednn_git_sha = get_submodule_commit(base_dir, "third_party/oneDNN")
517
ipex_cpu_ideep_git_sha = get_submodule_commit(base_dir, "third_party/ideep")
518
create_version_files(
519
    base_dir,
520
    ipex_build_version,
521
    ipex_git_sha,
522
    torch_git_sha,
523
    ipex_gpu_onednn_git_sha,
524
    ipex_cpu_ideep_git_sha,
525
)
526

527

528
def auto_format_python_code():
529
    script_path = os.path.join(base_dir, "scripts", "tools", "setup", "flake8.py")
530
    script_cmd = ["python"]
531
    script_cmd.append(script_path)
532
    subprocess.call(
533
        script_cmd,
534
        cwd=base_dir,
535
    )
536

537

538
# global setup modules
539
class IPEXClean(distutils.command.clean.clean, object):
540
    def run(self):
541
        import glob
542
        import re
543

544
        with open(".gitignore", "r") as f:
545
            ignores = f.read()
546
            pat = re.compile(r"^#( BEGIN NOT-CLEAN-FILES )?")
547
            for wildcard in filter(None, ignores.split("\n")):
548
                match = pat.match(wildcard)
549
                if match:
550
                    if match.group(1):
551
                        # Marker is found and stop reading .gitignore.
552
                        break
553
                # Ignore lines which begin with '#'.
554
                else:
555
                    for filename in glob.glob(wildcard):
556
                        try:
557
                            os.remove(filename)
558
                        except OSError:
559
                            shutil.rmtree(filename, ignore_errors=True)
560

561
        # It's an old-style class in Python 2.7...
562
        distutils.command.clean.clean.run(self)
563

564

565
def get_cpp_test_dir():
566
    project_root_dir = os.path.abspath(os.path.dirname(__file__))
567
    return os.path.join(project_root_dir, "tests", "cpu", "cpp")
568

569

570
def get_cpp_test_build_dir():
571
    cpp_test_build_dir = os.path.join(get_build_type_dir(), "tests", "cpu", "cpp")
572
    create_if_not_exist(cpp_test_build_dir)
573
    return cpp_test_build_dir
574

575

576
def get_pybind11_abi_compiler_flags():
577
    pybind11_abi_flags = []
578
    for pname in ["COMPILER_TYPE", "STDLIB", "BUILD_ABI"]:
579
        pval = getattr(torch._C, f"_PYBIND11_{pname}")
580
        if pval is not None:
581
            pybind11_abi_flags.append(f'-DPYBIND11_{pname}=\\"{pval}\\"')
582
    cl_flags = ""
583
    for flag in pybind11_abi_flags:
584
        cl_flags += flag + " "
585
    return cl_flags
586

587

588
def _gen_build_cfg_from_cmake(
589
    cmake_exec,
590
    project_root_dir,
591
    cmake_args,
592
    build_dir,
593
    build_env,
594
    use_ninja=True,
595
    build_gpu=False,
596
):
597
    if IS_WINDOWS:
598
        if use_ninja:
599
            check_call(
600
                [cmake_exec, project_root_dir, "-GNinja"] + cmake_args,
601
                cwd=build_dir,
602
                env=build_env,
603
            )
604
        else:
605
            # using MSVC generator
606
            if build_gpu:
607
                check_call(
608
                    [
609
                        cmake_exec,
610
                        project_root_dir,
611
                        "-G Visual Studio 17 2022",
612
                        "-T Intel C++ Compiler 2024",
613
                    ]
614
                    + cmake_args,
615
                    cwd=build_dir,
616
                    env=build_env,
617
                )
618
            else:
619
                check_call(
620
                    [
621
                        cmake_exec,
622
                        project_root_dir,
623
                        "-G Visual Studio 17 2022",
624
                        "-T Intel C++ Compiler 2024",
625
                    ]
626
                    + cmake_args,
627
                    cwd=build_dir,
628
                    env=build_env,
629
                )
630
    else:
631
        # Linux
632
        check_call(
633
            [cmake_exec, project_root_dir] + cmake_args, cwd=build_dir, env=build_env
634
        )
635

636

637
def _build_project(build_args, build_dir, build_env, use_ninja=True):
638
    if IS_WINDOWS:
639
        if use_ninja:
640
            check_call(["ninja"] + build_args, cwd=build_dir, env=build_env)
641
        else:
642
            # Current Windows MSVC needs manual build
643
            pass
644
    else:
645
        # Linux
646
        if use_ninja:
647
            check_call(["ninja"] + build_args, cwd=build_dir, env=build_env)
648
        else:
649
            check_call(["make"] + build_args, cwd=build_dir, env=build_env)
650

651

652
def define_build_options(args, **kwargs):
653
    for key, value in sorted(kwargs.items()):
654
        if value is not None:
655
            args.append("-D{}={}".format(key, value))
656

657

658
class IPEXCPPLibBuild(build_clib, object):
659
    def run(self):
660
        self.build_lib = os.path.relpath(get_package_dir())
661
        self.build_temp = os.path.relpath(get_build_type_dir())
662

663
        auto_format_python_code()
664

665
        cmake_exec = get_cmake_command()
666
        if cmake_exec is None:
667
            raise RuntimeError(
668
                "CMake must be installed to build the following extensions: "
669
                + ", ".join(e.name for e in self.extensions)
670
            )
671
        self.cmake = cmake_exec
672

673
        project_root_dir = get_project_dir()
674
        build_type_dir = get_build_type_dir()
675

676
        ipex_python_dir = get_ipex_python_dir()
677
        ipex_python_build_dir = get_ipex_python_build_dir()
678

679
        ipex_cpu_dir = get_ipex_cpu_dir()
680
        ipex_cpu_build_dir = get_ipex_cpu_build_dir()
681

682
        ipex_xpu_dir = get_xpu_project_dir()
683
        ipex_xpu_build_dir = get_xpu_project_build_dir()
684

685
        ipex_cppsdk_build_dir = get_ipex_cppsdk_build_dir()
686
        cpack_out_file = os.path.abspath(
687
            os.path.join(build_type_dir, "IPEXCPackConfig.cmake")
688
        )
689
        self_extract_script = "gen_self_extract.sh"
690

691
        if _get_build_target() == "cppsdk":
692
            cmake_prefix_path = torch_install_prefix
693
        else:
694
            cmake_prefix_path = torch.utils.cmake_prefix_path
695

696
        build_option_common = {
697
            "CMAKE_BUILD_TYPE": get_build_type(),
698
            "CMAKE_INSTALL_LIBDIR": "lib",
699
            "CMAKE_PREFIX_PATH": cmake_prefix_path,
700
            "CMAKE_INSTALL_PREFIX": os.path.abspath(get_package_dir()),
701
            "CMAKE_PROJECT_VERSION": get_version_num(),
702
            "PYTHON_PLATFORM_INFO": platform.platform(),
703
            "PYTHON_INCLUDE_DIR": sysconfig.get_paths()["include"],
704
            "PYTHON_EXECUTABLE": sys.executable,
705
            "IPEX_PROJ_NAME": PACKAGE_NAME,
706
            "LIBIPEX_GITREV": ipex_git_sha,
707
            "LIBIPEX_VERSION": ipex_build_version,
708
        }
709

710
        build_with_cpu = True  # Default ON
711
        build_with_xpu = False  # Default OFF
712

713
        use_ninja = False
714
        # Windows uses Ninja as default generator
715
        if IS_WINDOWS:
716
            use_ninja = True
717
        sequential_build = False
718

719
        cmake_common_args = []
720
        my_env = os.environ.copy()
721

722
        for var, val in my_env.items():
723
            if var.startswith(("BUILD_", "USE_", "CMAKE_")):
724
                if var == "CMAKE_PREFIX_PATH":
725
                    # XXX: Do NOT overwrite CMAKE_PREFIX_PATH. Append into the list, instead!
726
                    build_option_common[var] = ";".join(
727
                        [build_option_common[var], val.replace(":", ";")]
728
                    )
729
                    continue
730
                if var == "USE_NINJA" and val.upper() in ON_ENV_VAL:
731
                    use_ninja = True
732
                    cmake_common_args.append("-GNinja")
733
                    continue
734
                if IS_WINDOWS and var == "USE_MSVC" and val.upper() in ON_ENV_VAL:
735
                    use_ninja = False
736
                    continue
737
                if var == "BUILD_STATS" and val.upper() in ON_ENV_VAL:
738
                    sequential_build = True
739
                    # fall through
740
                if var == "BUILD_WITH_XPU" and val.upper() in ON_ENV_VAL:
741
                    build_with_xpu = True
742
                    # fall through
743
                if var == "BUILD_WITH_CPU" and val.upper() in OFF_ENV_VAL:
744
                    build_with_cpu = False
745
                    # fall through
746
                build_option_common[var] = val
747

748
        define_build_options(cmake_common_args, **build_option_common)
749

750
        nproc = min(int(os.environ.get("MAX_JOBS", os.cpu_count())), os.cpu_count())
751
        if sequential_build:
752
            nproc = 1
753
            print("WARNING: Practice as sequential build with single process !")
754

755
        build_args = ["-j", str(nproc), "install"]
756
        if _check_env_flag("VERBOSE") and use_ninja:
757
            build_args.append("-v")
758

759
        if build_with_xpu:
760
            # Generate cmake for XPU module:
761
            if os.path.isdir(ipex_xpu_dir) is False:
762
                raise RuntimeError(
763
                    "It maybe CPU only branch, and it is not contains XPU code."
764
                )
765

766
            gpu_cc, gpu_cxx = get_xpu_compliers()
767
            build_option_gpu = {
768
                **build_option_common,
769
                "BUILD_MODULE_TYPE": "GPU",
770
                "CMAKE_C_COMPILER": gpu_cc,
771
                "CMAKE_CXX_COMPILER": gpu_cxx,
772
            }
773

774
            if get_build_type() == "Debug":
775
                build_option_gpu = {
776
                    **build_option_gpu,
777
                    "BUILD_SEPARATE_OPS": "ON",
778
                    "USE_SYCL_ASSERT": "ON",
779
                    "USE_ITT_ANNOTATION": "ON",
780
                }
781

782
            cmake_args_gpu = []
783
            define_build_options(cmake_args_gpu, **build_option_gpu)
784
            _gen_build_cfg_from_cmake(
785
                cmake_exec,
786
                project_root_dir,
787
                cmake_args_gpu,
788
                ipex_xpu_build_dir,
789
                my_env,
790
                use_ninja=use_ninja,
791
                build_gpu=True,
792
            )
793

794
        if build_with_cpu:
795
            # Generate cmake for CPU module:
796
            cpu_cc, cpu_cxx = get_cpu_compliers()
797
            if cpu_cc is not None and cpu_cxx is not None:
798
                build_option_cpu = {
799
                    **build_option_common,
800
                    "BUILD_MODULE_TYPE": "CPU",
801
                    "CMAKE_C_COMPILER": cpu_cc,
802
                    "CMAKE_CXX_COMPILER": cpu_cxx,
803
                }
804
            else:
805
                build_option_cpu = {**build_option_common, "BUILD_MODULE_TYPE": "CPU"}
806

807
            cmake_args_cpu = []
808
            define_build_options(cmake_args_cpu, **build_option_cpu)
809
            _gen_build_cfg_from_cmake(
810
                cmake_exec,
811
                project_root_dir,
812
                cmake_args_cpu,
813
                ipex_cpu_build_dir,
814
                my_env,
815
                use_ninja=use_ninja,
816
            )
817

818
            # Generate cmake for the CPP UT
819
            build_option_cpp_test = {
820
                **build_option_common,
821
                "PROJECT_DIR": project_root_dir,
822
                "PYTORCH_INSTALL_DIR": pytorch_install_dir,
823
                "CPP_TEST_BUILD_DIR": get_cpp_test_build_dir(),
824
            }
825

826
            cmake_args_cpp_test = []
827
            define_build_options(cmake_args_cpp_test, **build_option_cpp_test)
828
            _gen_build_cfg_from_cmake(
829
                cmake_exec,
830
                get_cpp_test_dir(),
831
                cmake_args_cpp_test,
832
                get_cpp_test_build_dir(),
833
                my_env,
834
                use_ninja=use_ninja,
835
            )
836

837
        if _get_build_target() in ["develop", "python"]:
838
            # Generate cmake for common python module:
839
            build_option_python = {
840
                **build_option_common,
841
                "BUILD_MODULE_TYPE": "PYTHON",
842
                "PYBIND11_CL_FLAGS": get_pybind11_abi_compiler_flags(),
843
            }
844

845
            cmake_args_python = []
846
            define_build_options(cmake_args_python, **build_option_python)
847
            _gen_build_cfg_from_cmake(
848
                cmake_exec,
849
                project_root_dir,
850
                cmake_args_python,
851
                ipex_python_build_dir,
852
                my_env,
853
                use_ninja=use_ninja,
854
            )
855

856
        elif _get_build_target() == "cppsdk":
857
            # Generate cmake for CPPSDK package:
858
            build_option_cppsdk = {
859
                **build_option_common,
860
                "BUILD_MODULE_TYPE": "CPPSDK",
861
                "CPACK_CONFIG_FILE": cpack_out_file,
862
                "CPACK_OUTPUT_DIR": build_type_dir,
863
                "LIBIPEX_GEN_SCRIPT": self_extract_script,
864
            }
865

866
            cmake_args_cppsdk = []
867
            define_build_options(cmake_args_cppsdk, **build_option_cppsdk)
868
            _gen_build_cfg_from_cmake(
869
                cmake_exec,
870
                project_root_dir,
871
                cmake_args_cppsdk,
872
                ipex_cppsdk_build_dir,
873
                my_env,
874
                use_ninja=use_ninja,
875
            )
876

877
        if build_with_xpu:
878
            # Build XPU module:
879
            _build_project(build_args, ipex_xpu_build_dir, my_env, use_ninja=use_ninja)
880

881
        if build_with_cpu:
882
            # Build CPU module:
883
            _build_project(build_args, ipex_cpu_build_dir, my_env, use_ninja=use_ninja)
884

885
            # Build the CPP UT
886
            _build_project(
887
                build_args, get_cpp_test_build_dir(), my_env, use_ninja=use_ninja
888
            )
889

890
        if _get_build_target() in ["develop", "python"]:
891
            # Build common python module:
892
            _build_project(
893
                build_args, ipex_python_build_dir, my_env, use_ninja=use_ninja
894
            )
895

896
        elif _get_build_target() == "cppsdk":
897
            # Build CPPSDK package:
898
            _build_project(
899
                build_args, ipex_cppsdk_build_dir, my_env, use_ninja=use_ninja
900
            )
901
            cpack_exec = get_cpack_command()
902
            check_call([cpack_exec, "--config", cpack_out_file])
903
            gen_script_path = os.path.abspath(
904
                os.path.join(build_type_dir, self_extract_script)
905
            )
906
            if not os.path.isfile(gen_script_path):
907
                raise "Cannot find script to generate self-extract package in {}".format(
908
                    gen_script_path
909
                )
910
            check_call(gen_script_path, shell=True)
911

912
        # Copy the export library, header and cmake file to root/intel_extension_for_pytorch dir.
913
        # It is only copied in "develop" mode, which can save disk space in "install" mode.
914
        if _get_build_target() == "develop":
915
            ret = get_src_lib_and_dst()
916
            for src, dst in ret:
917
                self.copy_file(src, dst)
918

919

920
def get_src_lib_and_dst():
921
    ret = []
922
    generated_cpp_files = glob.glob(
923
        os.path.join(get_package_base_dir(), PACKAGE_NAME, "lib", "**/*.so"),
924
        recursive=True,
925
    )
926
    generated_cpp_files.extend(
927
        glob.glob(
928
            os.path.join(get_package_base_dir(), PACKAGE_NAME, "bin", "**/*.dll"),
929
            recursive=True,
930
        )
931
    )
932
    generated_cpp_files.extend(
933
        glob.glob(
934
            os.path.join(get_package_base_dir(), PACKAGE_NAME, "lib", "**/*.lib"),
935
            recursive=True,
936
        )
937
    )
938
    generated_cpp_files.extend(
939
        glob.glob(
940
            os.path.join(get_package_base_dir(), PACKAGE_NAME, "include", "**/*.h"),
941
            recursive=True,
942
        )
943
    )
944
    generated_cpp_files.extend(
945
        glob.glob(
946
            os.path.join(get_package_base_dir(), PACKAGE_NAME, "share", "**/*.cmake"),
947
            recursive=True,
948
        )
949
    )
950
    for src in generated_cpp_files:
951
        dst = os.path.join(
952
            get_project_dir(),
953
            PACKAGE_NAME,
954
            os.path.relpath(src, os.path.join(get_package_base_dir(), PACKAGE_NAME)),
955
        )
956
        dst_path = Path(dst)
957
        if not dst_path.parent.exists():
958
            Path(dst_path.parent).mkdir(parents=True, exist_ok=True)
959
        ret.append((src, dst))
960
    return ret
961

962

963
def get_src_py_and_dst():
964
    ret = []
965
    generated_python_files = glob.glob(
966
        os.path.join(get_project_dir(), PACKAGE_NAME, "**/*.py"), recursive=True
967
    )
968
    for src in generated_python_files:
969
        dst = os.path.join(
970
            get_package_base_dir(),
971
            PACKAGE_NAME,
972
            os.path.relpath(src, os.path.join(get_project_dir(), PACKAGE_NAME)),
973
        )
974
        dst_path = Path(dst)
975
        if not dst_path.parent.exists():
976
            Path(dst_path.parent).mkdir(parents=True, exist_ok=True)
977
        ret.append((src, dst))
978
    return ret
979

980

981
# python specific setup modules
982
class IPEXEggInfoBuild(egg_info, object):
983
    def finalize_options(self):
984
        super(IPEXEggInfoBuild, self).finalize_options()
985

986

987
class IPEXInstallCmd(install, object):
988
    def finalize_options(self):
989
        self.build_lib = os.path.relpath(get_package_base_dir())
990
        return super(IPEXInstallCmd, self).finalize_options()
991

992

993
class IPEXPythonPackageBuild(build_py, object):
994
    def run(self) -> None:
995
        ret = get_src_py_and_dst()
996
        for src, dst in ret:
997
            self.copy_file(src, dst)
998
        super(IPEXPythonPackageBuild, self).finalize_options()
999

1000

1001
def make_relative_rpath(path):
1002
    if IS_DARWIN:
1003
        return "-Wl,-rpath,@loader_path/" + path
1004
    elif IS_WINDOWS:
1005
        return path
1006
    else:
1007
        return "-Wl,-rpath,$ORIGIN/" + path
1008

1009

1010
def pyi_module():
1011
    main_libraries = ["intel-ext-pt-python"]
1012
    main_sources = [os.path.join(PACKAGE_NAME, "csrc", "_C.cpp")]
1013

1014
    include_dirs = [
1015
        os.path.realpath("."),
1016
        os.path.realpath(os.path.join(PACKAGE_NAME, "csrc")),
1017
        os.path.join(pytorch_install_dir, "include"),
1018
        os.path.join(pytorch_install_dir, "include", "torch", "csrc", "api", "include"),
1019
    ]
1020

1021
    library_dirs = ["lib", os.path.join(pytorch_install_dir, "lib")]
1022

1023
    if not IS_WINDOWS:
1024
        library_dirs = ["lib", os.path.join(pytorch_install_dir, "lib")]
1025

1026
        extra_compile_args = [
1027
            "-Wall",
1028
            "-Wextra",
1029
            "-Wno-strict-overflow",
1030
            "-Wno-unused-parameter",
1031
            "-Wno-missing-field-initializers",
1032
            "-Wno-write-strings",
1033
            "-Wno-unknown-pragmas",
1034
            # This is required for Python 2 declarations that are deprecated in 3.
1035
            "-Wno-deprecated-declarations",
1036
            # Python 2.6 requires -fno-strict-aliasing, see
1037
            # http://legacy.python.org/dev/peps/pep-3123/
1038
            # We also depend on it in our code (even Python 3).
1039
            "-fno-strict-aliasing",
1040
            # Clang has an unfixed bug leading to spurious missing
1041
            # braces warnings, see
1042
            # https://bugs.llvm.org/show_bug.cgi?id=21629
1043
            "-Wno-missing-braces",
1044
        ]
1045

1046
        C_ext = CppExtension(
1047
            "{}._C".format(PACKAGE_NAME),
1048
            libraries=main_libraries,
1049
            sources=main_sources,
1050
            language="c++",
1051
            extra_compile_args=extra_compile_args,
1052
            include_dirs=include_dirs,
1053
            library_dirs=library_dirs,
1054
            extra_link_args=[make_relative_rpath("lib")],
1055
        )
1056
    else:
1057
        library_dirs = ["bin", os.path.join(pytorch_install_dir, "lib")]
1058
        extra_link_args = ["/NODEFAULTLIB:LIBCMT.LIB"]
1059
        # /MD links against DLL runtime
1060
        # and matches the flags set for protobuf and ONNX
1061
        # /EHsc is about standard C++ exception handling
1062
        # /DNOMINMAX removes builtin min/max functions
1063
        # /wdXXXX disables warning no. XXXX
1064
        extra_compile_args = [
1065
            "/MD",
1066
            "/EHsc",
1067
            "/DNOMINMAX",
1068
            "/wd4267",
1069
            "/wd4251",
1070
            "/wd4522",
1071
            "/wd4522",
1072
            "/wd4838",
1073
            "/wd4305",
1074
            "/wd4244",
1075
            "/wd4190",
1076
            "/wd4101",
1077
            "/wd4996",
1078
            "/wd4275",
1079
        ]
1080
        C_ext = CppExtension(
1081
            "{}._C".format(PACKAGE_NAME),
1082
            libraries=main_libraries,
1083
            sources=main_sources,
1084
            language="c++",
1085
            extra_compile_args=extra_compile_args,
1086
            include_dirs=include_dirs,
1087
            library_dirs=library_dirs,
1088
            extra_link_args=extra_link_args,
1089
        )
1090
    return C_ext
1091

1092

1093
def pyi_isa_help_module():
1094
    main_libraries = []
1095
    main_sources = [
1096
        os.path.join(PACKAGE_NAME, "csrc", "_isa_help_main.cpp"),
1097
        os.path.join(PACKAGE_NAME, "csrc", "cpu", "isa_help", "isa_help.cpp"),
1098
        os.path.join("csrc", "cpu", "isa", "cpu_feature.cpp"),
1099
    ]
1100

1101
    include_dirs = [
1102
        os.path.realpath("."),
1103
        os.path.realpath(os.path.join("csrc", "cpu", "isa")),
1104
        os.path.realpath(os.path.join(PACKAGE_NAME, "csrc")),
1105
        os.path.join(pytorch_install_dir, "include"),
1106
        os.path.join(pytorch_install_dir, "include", "torch", "csrc", "api", "include"),
1107
    ]
1108

1109
    if not IS_WINDOWS:
1110
        library_dirs = ["lib", os.path.join(pytorch_install_dir, "lib")]
1111

1112
        extra_compile_args = [
1113
            "-Wall",
1114
            "-Wextra",
1115
            "-Wno-strict-overflow",
1116
            "-Wno-unused-parameter",
1117
            "-Wno-missing-field-initializers",
1118
            "-Wno-write-strings",
1119
            "-Wno-unknown-pragmas",
1120
            # This is required for Python 2 declarations that are deprecated in 3.
1121
            "-Wno-deprecated-declarations",
1122
            # Python 2.6 requires -fno-strict-aliasing, see
1123
            # http://legacy.python.org/dev/peps/pep-3123/
1124
            # We also depend on it in our code (even Python 3).
1125
            "-fno-strict-aliasing",
1126
            # Clang has an unfixed bug leading to spurious missing
1127
            # braces warnings, see
1128
            # https://bugs.llvm.org/show_bug.cgi?id=21629
1129
            "-Wno-missing-braces",
1130
        ]
1131

1132
        C_ext = CppExtension(
1133
            "{}._isa_help".format(PACKAGE_NAME),
1134
            libraries=main_libraries,
1135
            sources=main_sources,
1136
            language="c++",
1137
            extra_compile_args=extra_compile_args,
1138
            include_dirs=include_dirs,
1139
            library_dirs=library_dirs,
1140
            extra_link_args=[make_relative_rpath("lib")],
1141
        )
1142
    else:
1143
        library_dirs = ["bin", os.path.join(pytorch_install_dir, "lib")]
1144
        extra_link_args = ["/NODEFAULTLIB:LIBCMT.LIB"]
1145
        # /MD links against DLL runtime
1146
        # and matches the flags set for protobuf and ONNX
1147
        # /EHsc is about standard C++ exception handling
1148
        # /DNOMINMAX removes builtin min/max functions
1149
        # /wdXXXX disables warning no. XXXX
1150
        extra_compile_args = [
1151
            "/MD",
1152
            "/EHsc",
1153
            "/DNOMINMAX",
1154
            "/wd4267",
1155
            "/wd4251",
1156
            "/wd4522",
1157
            "/wd4522",
1158
            "/wd4838",
1159
            "/wd4305",
1160
            "/wd4244",
1161
            "/wd4190",
1162
            "/wd4101",
1163
            "/wd4996",
1164
            "/wd4275",
1165
        ]
1166
        C_ext = CppExtension(
1167
            "{}._isa_help".format(PACKAGE_NAME),
1168
            libraries=main_libraries,
1169
            sources=main_sources,
1170
            language="c++",
1171
            extra_compile_args=extra_compile_args,
1172
            include_dirs=include_dirs,
1173
            library_dirs=library_dirs,
1174
            extra_link_args=extra_link_args,
1175
        )
1176
    return C_ext
1177

1178

1179
ext_modules = []
1180
cmdclass = {
1181
    "build_clib": IPEXCPPLibBuild,
1182
    "bdist_cppsdk": IPEXCPPLibBuild,
1183
    "clean": IPEXClean,
1184
}
1185

1186

1187
def fill_python_target_cmd(cmdclass, ext_modules):
1188
    class IPEXExtBuild(BuildExtension):
1189
        def run(self):
1190
            self.run_command("build_clib")
1191

1192
            self.build_lib = os.path.relpath(get_package_base_dir())
1193
            self.build_temp = os.path.relpath(get_build_type_dir())
1194
            self.library_dirs.append(os.path.relpath(get_package_lib_dir()))
1195
            super(IPEXExtBuild, self).run()
1196

1197
    cmdclass["build_ext"] = IPEXExtBuild
1198
    cmdclass["build_py"] = IPEXPythonPackageBuild
1199
    cmdclass["egg_info"] = IPEXEggInfoBuild
1200
    cmdclass["install"] = IPEXInstallCmd
1201
    ext_modules.append(pyi_module())
1202
    ext_modules.append(pyi_isa_help_module())
1203

1204

1205
if _get_build_target() in ["develop", "python"]:
1206
    fill_python_target_cmd(cmdclass, ext_modules)
1207

1208

1209
long_description = ""
1210
this_directory = os.path.abspath(os.path.dirname(__file__))
1211
with open(os.path.join(this_directory, "README.md"), encoding="utf-8") as f:
1212
    long_description = f.read()
1213

1214
entry_points = {
1215
    "console_scripts": [
1216
        "ipexrun = {}.launcher:main".format(PACKAGE_NAME),
1217
    ]
1218
}
1219

1220

1221
setup(
1222
    name=PACKAGE_NAME,
1223
    version=ipex_build_version,
1224
    description="Intel® Extension for PyTorch*",
1225
    long_description=long_description,
1226
    long_description_content_type="text/markdown",
1227
    url="https://github.com/intel/intel-extension-for-pytorch",
1228
    author="Intel Corp.",
1229
    install_requires=_build_installation_dependency(),
1230
    packages=[PACKAGE_NAME],
1231
    package_data={PACKAGE_NAME: ["*.so", "lib/*.so", "bin/*.dll", "lib/*.lib"]},
1232
    zip_safe=False,
1233
    ext_modules=ext_modules,
1234
    cmdclass=cmdclass,
1235
    entry_points=entry_points,
1236
    license="https://www.apache.org/licenses/LICENSE-2.0",
1237
    classifiers=[
1238
        "License :: OSI Approved :: Apache Software License",
1239
    ],
1240
)
1241

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.