1.[推理部署]👉Mac源码编译TensorFlow C++指北
2.MacOS 下交叉编译的源码折腾笔记
3.极简入门TensorFlow C++源码
4.电脑macOS mojave 10.14.6, 编译tensorflow2.6解决SSE4.1 SSE4.2 AVX指令集问题。
5.å¦ä½ä½¿ç¨bazel build
6.ONOS 从零入门教学 (应用程式新增,安装安装及测试)
[推理部署]👉Mac源码编译TensorFlow C++指北
在Mac环境下编译TensorFlow C++源码,源码需要完成以下步骤,安装以避免可能的源码编译问题,确保顺利构建。安装电子病历源码pb
首先,源码确认系统环境满足要求。安装需有Xcode和Command Line Tools,源码JDK 1.8.0版本以支持编译过程中所需的安装Java环境,以及Bazel工具,源码TensorFlow依赖此工具进行编译。安装特别注意Bazel版本需与TensorFlow对应,源码如TensorFlow 1.对应Bazel 0..1。安装
接下里,源码安装依赖,包括JDK和Bazel。JDK安装时需检查电脑中是否已安装,并确保正确安装。使用HomeBrew安装Bazel,通过命令行接受协议,并使用`--user`指令确保安装在个人目录的`bin`文件夹下,同时设置`.bazelrc`路径为`$HOME/.bazelrc`。
安装自动化工具`automake`和使用Python3.7.5在虚拟环境中构建TensorFlow C++源码。推荐使用清华镜像源加速`pip`的安装过程。通过`git clone`方式下载TensorFlow源码,确保checkout至r1.分支。调整域名映射以提升`git clone`速度。
进行编译选项配置,通常在TensorFlow文件夹内运行命令,根据提示选择默认选项。
开始编译TensorFlow,此过程可能需要较长时间,完成后,应在`bazel-bin/tensorflow`目录下找到编译好的`libtensorflow_cc.so`和`libtensorflow_framework.1.dylib`文件。
若遇到`Undefined symbols for architecture x_: “_CFRelease”`错误,这通常与创建软连接有关,无需特别处理。若需要手动安装额外依赖库,如Eigen3,辽宁金寨源码出售可参考相关指南。
编译完成后,可对C++接口进行测试,验证编译过程的正确性。通常情况下,Mac下的TensorFlow 1. C++源码编译完成。
最后,编译TFLite,生成的动态链接库将保存在指定目录下。在`CMakelists.txt`文件中增加对应配置项,以完成TFLite的构建。
总结而言,Mac下TensorFlow 1. C++源码编译及TFLite的构建,需要遵循上述步骤,并确保环境与工具版本的兼容性,以顺利进行编译过程。Linux系统下的编译方式相似,但具体细节可能有所不同。
MacOS 下交叉编译的折腾笔记
探索 MacOS 下的交叉编译技巧
本文作为系列 “折腾笔记” 的一部分,旨在以直白的方式展示交叉编译过程中的实际操作,而非追求最佳实践。本教程将为初学者提供一个直观理解交叉编译的基本框架,并在后续篇章中深入探讨基于 Bazel 的交叉编译最佳实践,以及如何在树莓派等目标平台上运行包含深度学习模型的小程序。
值得注意的是,尽管 MacOS 广为人知,但并不等同于 Linux。在 MacOS 上进行交叉编译时,往往面临着一些挑战。例如,某些 TensorFlowLite 提供的交叉编译工具或 Linaro 系列工具仅在 Linux 环境下可用。因此,建议在进行 MacOS 下的交叉编译时,采用 Docker 技术运行 Linux 系统,从而有效绕过这些平台限制。
对于交叉编译的入门理解与实践思路,我们需要明确其本质是利用能将源代码转换为目标平台机器语言的编译器。在进行树莓派等目标平台的交叉编译时,通常需要使用特定于目标架构(如 ARM)的bsc看合约源码编译器,例如 arm-linux-gnueabihf-gcc。
实际操作中,交叉编译流程可以概括为以下步骤:
1. **依赖环境安装**:利用 Homebrew 等包管理工具安装必要的依赖项。
2. **环境准备**:从树莓派设备上复制相关 gcc 及其配套环境。
3. **环境检查**:确保当前工作目录正确无误。
4. **源代码准备**:编写或获取待编译的源代码文件,如 `hello_cross_comile.cc`。
5. **交叉编译执行**:利用 LLVM 工具链结合 arm-linux-gnueabihf-binutils 进行交叉编译。
6. **构建输出**:运行特定编译脚本(通常封装为 `.sh` 文件)生成目标平台可执行文件(如 `hello`),随后将该文件传输至树莓派等目标平台进行执行。
推荐阅读资源:
4. **[野火]i.MX Linux开发实战指南**:该文档提供了一个全面且详细的交叉编译指南,虽然不直接支持 MacOS,但通过开启 Docker 环境,可以轻松实现 MacOS 下的交叉编译。
Crosstool-ng:尽管这是 MacOS 下公认的交叉编译解决方案,但其操作复杂,且存在系统崩溃风险。对于坚持使用此方案的开发者,可参考他人提供的 Docker 镜像,例如 **Dockfile**,但同样建议考虑使用更易管理的 Linux 操作系统(如 Ubuntu)作为 Docker 容器的基础环境。
极简入门TensorFlow C++源码
前一段时间,我专注在框架开发上,并偶尔协助业务同学优化使用TensorFlow的代码。在观看dmlc/relay、nnvm的代码时,我发现了它们的有趣之处。我也对TensorFlow的Graph IR、PaddlePaddle的Graph IR产生了兴趣,上周五在阅读代码时,无意间听到了一个数据竞赛群讨论框架的底层实现。几位算法大佬提到了看底层源码可能较为繁琐,因为这类代码通常相对容易理解。在与群内伙伴的交流后,我萌生了撰写一篇关于如何阅读TensorFlow或其他框架底层源码的文章。
选择合适版本的bazel,对于阅读TensorFlow源码至关重要。应使用版本为0..0的bazel来拉取TF2.0代码,因为太高的报名考试程序源码版本或太低的版本可能影响阅读体验。在安装了合适的bazel版本后,使用clion上的bazel插件进行导入,然后配置编译,导入项目,等待clion编译整个项目。完成编译后,就能愉快地阅读代码,甚至于protobuf生成的文件也能轻松跳转。
使用c++编译模型是TensorFlow的另一面。尝试使用c++编写模型代码,可以深入理解TensorFlow的底层机制。主要函数包括CreateGraphDef、ConcurrentSteps、ConcurrentSessions等。通过这些函数,可以构建计算图,定义节点、常量变量、操作符等。这为理解TensorFlow的逻辑提供了直观的视角。
深入分析代码后,可以了解到TensorFlow的GraphDef机制、Square类的实现、注册到特定op的过程、functor的使用以及最终的实现逻辑。这有助于理解TensorFlow的核心原理,并在阅读源码时进行更深入的思考。
除了阅读源码,还可以通过编写测试用例来增强理解。TensorFlow提供了丰富的测试用例,如在client_session_test.cc中运行测试程序,可以验证代码的正确性。这不仅有助于理解代码,还能提高对TensorFlow框架的掌握程度。
阅读源码只是理解TensorFlow原理的开始,深入行业论文和请教行业专家是进一步深入学习的关键。网络上关于机器学习系统的资料丰富多样,但缺少系统性的课程。希望官方能够分享更多框架的商城源码脚本下载干货,并期待在学习过程中总结和分享更多资源。阅读源码虽然复杂,但其背后蕴含的原理和逻辑十分有趣。
电脑macOS mojave ..6, 编译tensorflow2.6解决SSE4.1 SSE4.2 AVX指令集问题。
针对macOS mojave ..6系统用户在编译tensorflow 2.6版本时遇到的SSE4.1、SSE4.2和AVX指令集问题,以下为解决步骤:
首先,前往tensorflow源码下载页面,下载v2.6.0版本。
然后,进入下载后的目录,定位至v2.6.0。
接下来,准备必要的软件环境。确保已安装java和minconda。
开始编译tensorflow时,关键在于使用优化指令集。在执行编译命令时,加入参数`-march=native`以进行cpu指令集优化。
使用命令行进行编译:`bazelisk build -c opt --copt=-march=native //tensorflow/tools/pip_package:build_pip_package`。
编译完成后,在/tmp/tensorflow_pkg目录下找到生成的wheel文件。使用pip进行安装,即可完成tensorflow 2.6版本的安装。
完成编译与安装后,用户可根据需要下载tensorflow-2.6.0-cp-cpm-macosx___x_.whl文件。提取码为kkli。
å¦ä½ä½¿ç¨bazel build
å®è£
å®è£ è¿ç¨è¯·åè: /example
$ cat > src/main/java/com/example/ProjectRunner.java <<EOF
package com.example;
public class ProjectRunner {
public static void main(String args[]) {
Greeting.sayHi();
}
}
EOF
$ cat > src/main/java/com/example/Greeting.java <<EOF
package com.example;
public class Greeting {
public static void sayHi() {
System.out.println("Hi!");
}
}
EOF
Bazeléè¿å·¥ä½åºä¸ææå为 BUILD çæ件æ¥è§£æéè¦æ建ç项ç®ä¿¡æ¯ï¼å æ¤ï¼æ们éè¦å å¨ ~/gitroot/my-project ç®å½å建ä¸ä¸ª BUILD æ建æ件ãä¸é¢æ¯BUILDæ建æ件çå 容ï¼
# ~/gitroot/my-project/BUILD
java_binary(
name = "my-runner",
srcs = glob(["**/*.java"]),
main_class = "com.example.ProjectRunner",
)
BUILDæ件éç¨ç±»ä¼¼Pythonçè¯æ³ãè½ç¶ä¸è½å å«ä»»æçPythonè¯æ³ï¼ä½æ¯BUILDæ件ä¸çæ¯ä¸ªæ建è§åçèµ·æ¥é½è±¡æ¯ä¸ä¸ªPythonå½æ°è°ç¨ï¼èä¸ä½ ä¹å¯ä»¥ç¨ "#" å¼å¤´æ¥æ·»å åè¡æ³¨éã
java_binary æ¯ä¸ä¸ªæ建è§åãå ¶ä¸ name 对åºä¸ä¸ªæ建ç®æ çæ è¯ç¬¦ï¼å¯ç¨ç¨å®æ¥åBazelæå®æ建åªä¸ªé¡¹ç®ãsrcs 对åºä¸ä¸ªæºæ件å表ï¼Bazeléè¦å°è¿äºæºæ件ç¼è¯ä¸ºäºè¿å¶æ件ãå ¶ä¸ glob(["**/*.java"]) 表示éå½å å«æ¯ä¸ªåç®å½ä¸ä»¥æ¯ä¸ª .java 为åç¼åçæ件ãcom.example.ProjectRunner æå®å å«mainæ¹æ³çç±»ã
ç°å¨å¯ä»¥ç¨ä¸é¢çå½ä»¤æ建è¿ä¸ªJavaç¨åºäºï¼
$ cd ~/gitroot/my-project
$ bazel build //:my-runner
INFO: Found 1 target...
Target //:my-runner up-to-date:
bazel-bin/my-runner.jar
bazel-bin/my-runner
INFO: Elapsed time: 1.s, Critical Path: 0.s
$ bazel-bin/my-runner
Hi!
æåï¼ä½ å·²ç»æåæ建äºç¬¬ä¸ä¸ªBazel项ç®äºï¼
æ·»å ä¾èµå ³ç³»
对äºå°é¡¹ç®å建ä¸ä¸ªè§åæ¯å¯ä»¥çï¼ä½æ¯éç项ç®çå大ï¼åéè¦åå«æ建项ç®çä¸åçé¨ä»¶ï¼æç»åç»è£ æ产åãè¿ç§æ建æ¹å¼å¯ä»¥é¿å å 为å±é¨ç»å°çä¿®æ¹å¿å¯¼è´éç°æ建æ´ä¸ªåºç¨ï¼åæ¶ä¸åçæ建æ¥éª¤å¯ä»¥å¾å¥½å°å¹¶åæ§è¡ä»¥æé«æ建æçã
æ们ç°å¨å°ä¸ä¸ªé¡¹ç®æå为两个é¨åç¬ç«æ建ï¼åæ¶è®¾ç½®å®ä»¬ä¹é´çä¾èµå ³ç³»ãåºäºä¸é¢çä¾åï¼æ们éåäºBUILDæ建æ件ï¼
java_binary(
name = "my-other-runner",
srcs = ["src/main/java/com/example/ProjectRunner.java"],
main_class = "com.example.ProjectRunner",
deps = [":greeter"],
)
java_library(
name = "greeter",
srcs = ["src/main/java/com/example/Greeting.java"],
)
è½ç¶æºæ件æ¯ä¸æ ·çï¼ä½æ¯ç°å¨Bazelå°éç¨ä¸åçæ¹å¼æ¥æ建ï¼é¦å æ¯æ建 greeteråºï¼ç¶åæ¯æ建 my-other-runnerãå¯ä»¥å¨æ建æååç«å»è¿è¡ //:my-other-runnerï¼
$ bazel run //:my-other-runner
INFO: Found 1 target...
Target //:my-other-runner up-to-date:
bazel-bin/my-other-runner.jar
bazel-bin/my-other-runner
INFO: Elapsed time: 2.s, Critical Path: 1.s
INFO: Running command line: bazel-bin/my-other-runner
Hi!
ç°å¨å¦æä½ æ¹å¨ProjectRunner.java代ç 并éæ°æ建my-other-runnerç®æ ï¼Greeting.javaæ件å 为没æååèä¸ä¼éç°ç¼è¯ã
使ç¨å¤ä¸ªå ï¼Packagesï¼
对äºæ´å¤§ç项ç®ï¼æ们é常éè¦å°å®ä»¬æåå°å¤ä¸ªç®å½ä¸ãä½ å¯ä»¥ç¨ç±»ä¼¼//path/to/directory:target-nameçååå¼ç¨å¨å ¶ä»BUILDæ件å®ä¹çç®æ ãå设src/main/java/com/example/æä¸ä¸ªcmdline/åç®å½ï¼å å«ä¸é¢çæ件ï¼
$ mkdir -p src/main/java/com/example/cmdline
$ cat > src/main/java/com/example/cmdline/Runner.java <<EOF
package com.example.cmdline;
import com.example.Greeting;
public class Runner {
public static void main(String args[]) {
Greeting.sayHi();
}
}
EOF
Runner.javaä¾èµcom.example.Greetingï¼å æ¤æ们éè¦å¨src/main/java/com/example/cmdline/BUILDæ建æ件ä¸æ·»å ç¸åºçä¾èµè§åï¼
# ~/gitroot/my-project/src/main/java/com/example/cmdline/BUILD
java_binary(
name = "runner",
srcs = ["Runner.java"],
main_class = "com.example.cmdline.Runner",
deps = ["//:greeter"]
)
ç¶èï¼é»è®¤æ åµä¸æ建ç®æ é½æ¯ ç§æ çãä¹å°±æ¯è¯´ï¼æ们åªè½å¨åä¸ä¸ªBUILDæ件ä¸è¢«å¼ç¨ãè¿å¯ä»¥é¿å å°å¾å¤å®ç°çç»èæ´æ¼ç»å ¬å ±çæ¥å£ï¼ä½æ¯ä¹æå³çæ们éè¦æå·¥å 许runneræä¾èµç//:greeterç®æ ãå°±æ¯ç±»ä¼¼ä¸é¢è¿ä¸ªå¨æ建runnerç®æ æ¶éå°çé误ï¼
$ bazel build //src/main/java/com/example/cmdline:runner
ERROR: /home/user/gitroot/my-project/src/main/java/com/example/cmdline/BUILD:2:1:
Target '//:greeter' is not visible from target '//src/main/java/com/example/cmdline:runner'.
Check the visibility declaration of the former target if you think the dependency is legitimate.
ERROR: Analysis of target '//src/main/java/com/example/cmdline:runner' failed; build aborted.
INFO: Elapsed time: 0.s
å¯ç¨éè¿å¨BUILDæ件å¢å visibility = levelå±æ§æ¥æ¹åç®æ çå¯é´èå´ãä¸é¢æ¯éè¿å¨~/gitroot/my-project/BUILDæ件å¢å å¯è§è§åï¼æ¥æ¹ågreeterç®æ çå¯è§èå´ï¼
java_library(
name = "greeter",
srcs = ["src/main/java/com/example/Greeting.java"],
visibility = ["//src/main/java/com/example/cmdline:__pkg__"],
)
è¿ä¸ªè§å表示//:greeterç®æ 对äº//src/main/java/com/example/cmdlineå æ¯å¯è§çãç°å¨æ们å¯ä»¥éæ°æ建runnerç®æ ç¨åºï¼
$ bazel run //src/main/java/com/example/cmdline:runner
INFO: Found 1 target...
Target //src/main/java/com/example/cmdline:runner up-to-date:
bazel-bin/src/main/java/com/example/cmdline/runner.jar
bazel-bin/src/main/java/com/example/cmdline/runner
INFO: Elapsed time: 1.s, Critical Path: 0.s
INFO: Running command line: bazel-bin/src/main/java/com/example/cmdline/runner
Hi!
åèææ¡£ ä¸æå¯è§æ§é 置说æã
é¨ç½²
å¦æä½ æ¥ç bazel-bin/src/main/java/com/example/cmdline/runner.jar çå 容ï¼å¯ä»¥çå°éé¢åªå å«äºRunner.classï¼å¹¶æ²¡æä¿æ¤æä¾èµçGreeting.classï¼
$ jar tf bazel-bin/src/main/java/com/example/cmdline/runner.jar
META-INF/
META-INF/MANIFEST.MF
com/
com/example/
com/example/cmdline/
com/example/cmdline/Runner.class
è¿åªè½å¨æ¬æºæ£å¸¸å·¥ä½ï¼å 为Bazelçrunnerèæ¬å·²ç»å°greeter jaræ·»å å°äºclasspathï¼ï¼ä½æ¯å¦æå°runner.jaråç¬å¤å¶å°å¦ä¸å°æºå¨ä¸è®²ä¸è½æ£å¸¸è¿è¡ãå¦ææ³è¦æ建å¯ç¨äºé¨ç½²åå¸çèªå å«ææä¾èµçç®æ ï¼å¯ä»¥æ建runner_deploy.jarç®æ ï¼ç±»ä¼¼<target-name>_deploy.jar以_deploy为åç¼çåå对åºå¯é¨ç½²ç®æ ï¼ã
$ bazel build //src/main/java/com/example/cmdline:runner_deploy.jar
INFO: Found 1 target...
Target //src/main/java/com/example/cmdline:runner_deploy.jar up-to-date:
bazel-bin/src/main/java/com/example/cmdline/runner_deploy.jar
INFO: Elapsed time: 1.s, Critical Path: 0.s
runner_deploy.jarä¸å°å å«å ¨é¨çä¾èµã
ä¸ä¸æ¥
ç°å¨ï¼æ¨å¯ä»¥å建èªå·±çç®æ 并ç»è£ æç»äº§åäºãæ¥ä¸æ¥ï¼å¯æ¥ç ç¸å ³æç¨ åå«å¦ä¹ å¦ä½ç¨Bazelæ建ä¸ä¸ªæå¡å¨ãAndroidåiOSåºç¨ãä¹å¯ä»¥åè ç¨æ·æåè·å¾æ´å¤çä¿¡æ¯ãå¦ææé®é¢çè¯ï¼å¯ä»¥å° bazel-discuss 论åæé®ã
ONOS 从零入门教学 (应用程式新增,安装及测试)
本文将介绍如何从零开始学习并使用ONOS,包括安装、配置和测试。首先,你需要获取ONOS的源代码并将其添加到.bashrc或.bash_profile中,使用预设的alias进行操作。然后使用构建工具(原为buck,现已更改为bazel)构建ONOS,并进行单元测试。
接下来,你可以在本地计算机上启动ONOS服务器,使用另一个终端开启ONOS控制台。成功后,会看到ONOS预设使用端口作为控制台。此时,恭喜你,已经成功在本地机上启动了ONOS。
ONOS还提供了图形用户界面(UI)界面,预设使用端口。你可以通过构建一个简单的SDN网络,包含4个Open vSwitch和9个主机,可以构建tree,2,3网络拓扑。在ONOS UI界面中,看到控制器识别的4台Open vSwitch,但主机未显示。这是因为Open vSwitch尚未知道主机的存在。你需要执行ping操作,控制器才会在交换机中安装flow。回到ONOS UI界面,现在应该能看到正确的显示。
ONOS中的应用是通过maven构建的,因此使用maven构建自己的应用。首先使用ONOS提供的工具将maven所需的artifacts推送到~/.m2。在外部路径或使用ONOS已打包的工具构建。注意,在pom.xml中未注释onos.app.name和onos.app.origin,会导致无法生成.oar文件。完成构建后,你应该能看到构建成功的画面。构建完成后的资料夹结构,有了最简单的maven结构后,你可以根据需求开始编写自己的ONOS应用。
最后,学习如何安装自己的ONOS应用。假设你已经编写了一个应用,例如onos-app-samples中的oneping。首先复制onos-app-samples到本地计算机中。onos-app-samples是一个包含ONOS样本应用的专案。使用onos-app-samples/oneping中的命令生成OAR档以用于安装。完成生成OAR档后,进入ONOS console执行安装命令,应用将被添加到ONOS中。最后,激活应用以使其可用,同样可以将其去激活。ONOS应用的安装档使用OAR作为格式。
实战!用Bazel来管理iOS程序
在探索Bazel作为iOS项目管理工具的过程中,我总结了以下几点原因促使我选择Bazel而非Xcode:
首先,Bazel提供更好的代码审查和依赖管理。Xcode的编译设置分散在多个文件中(xcscheme、pbxproj和xcconfig),使得代码审查变得困难。相反,Bazel的配置统一且可追踪,有利于代码审查流程。
其次,Bazel具有高效的缓存机制和快速增量编译能力。Xcode的编译缓存管理效率低下,即使是细微的设置改动也可能导致全量编译。相比之下,Bazel仅对发生变化的文件或依赖进行编译,切换分支也不会显著影响编译速度。
此外,Bazel支持远程缓存,这在项目规模增大时能显著提高编译效率。它还提供了更多模块化实践的友好环境,支持Swift等语言的大型项目开发。
选择迁移Bazel的时机因工程团队规模和需求而异。在感受到Xcode编译系统的不足(如长时间编译时间、单体大项目或持续集成工具频繁报错)时,迁移可能需要几个月的时间。而对于小型团队,迁移Bazel可能不是当前的首要任务。
配置阶段涉及安装工具(如Bazelisk和Tulsi)和调整文件结构。在源码库中创建WORKSPACE文件以整合规则,使用generate_xcodeproj.sh脚本生成Xcode项目。同时,通过PodToBUILD项目自动将CocoaPods依赖转换为Bazel兼容的格式。
处理CocoaPods依赖时,利用PodToBUILD将现有项目的依赖转换为Bazel格式,然后通过特定命令将依赖复制到源码库中。对于某些依赖,如Google的Protobuf,可以将官方的BUILD文件替换原有的CocoaPods配置。其他依赖通常通过Bazel的编译规则进行导入。
在处理C++支持时,需要手动创建自定义的toolchain并将其集成到本地项目中,以确保使用C++。此外,还需要关注Bridging header的配置、Provisioning文件、entitlement设置、以及手机测试和打包的相关步骤。
在Bazel下进行单元测试时,注意区分Hosted Tests与ios_unit_test的使用场景。对于大多数测试应转换为单元测试,而对于依赖特定环境的测试(如SnapshotTesting),则保持Hosted Tests的使用。
将Bazel集成至持续集成系统中,如Bitrise,可以简化测试和打包流程。通过共享缓存,可以进一步提升持续集成的编译速度。同时,使用Bazel的select_a_variant函数选择性地编译不同版本的程序,如针对Apple的提交版本。
随着项目的深入使用Bazel,可以探索更多的代码生成技术,例如自动将配置文件(如JSON文件)生成固定Swift文件,直接嵌入程序中,减少加载步骤。
迁移Bazel虽然需要一定的前期投入,但相对于之前的切换经验(如从Xcode Workspace到Buck),过程变得更加顺畅。对于大型依赖复杂的项目,迁移工作量也相对较小,通常只需几天时间。
尽管Bazel已提供了良好的基础支持,仍有改进空间,尤其是在工具集成与代码生成的自动化方面。此外,社区的反馈和讨论对于进一步优化迁移过程和利用Bazel的潜力至关重要。
从源码build Tensorflow2.6.5的记录
.从源码编译Tensorflow2.6.5踩坑记录,笔者经过一天的努力,失败四次后终于成功。Tensorflow2.6.5是截至.时,能够从源码编译的最新版本。
0 - 前期准备
为了对Tensorflow进行大规模修改并完成科研工作,笔者有从源码编译Tensorflow的需求。平时更常用的做法是在conda环境中pip install tensorflow,有时为了环境隔离方便打包,会用docker先套住,再上conda + pip安装。
1 - 资料汇总
教程参考:
另注:bazel的编译可以使用换源清华镜像(不是必要)。整体配置流程的根本依据还是官方的教程,但它的教程有些点和坑没有涉及到,所以多方材料了解。
2 - 整体流程
2.1 确定配置目标
官网上给到了配置目标,和对应的版本匹配关系(这张表里缺少了对numpy的版本要求)。笔者最后(在docker中)配置成功的版本为tensorflow2.6.5 numpy1..5 Python3.7. GCC7.5.0 CUDA.3 Bazel3.7.2。
2.2 开始配置
为了打包方便和编译环境隔离,在docker中进行了以下配置:
2. 安装TensorFlow pip软件包依赖项,其编译过程依赖于这些包。
3. Git Tensorflow源代码包。
4. 安装编译工具Bazel。
官网的介绍:(1)您需要安装Bazel,才能构建TensorFlow。您可以使用Bazelisk轻松安装Bazel,并且Bazelisk可以自动为TensorFlow下载合适的Bazel版本。为便于使用,请在PATH中将Bazelisk添加为bazel可执行文件。(2)如果没有Bazelisk,您可以手动安装Bazel。请务必安装受支持的Bazel版本,可以是tensorflow/configure.py中指定的介于_TF_MIN_BAZEL_VERSION和_TF_MAX_BAZEL_VERSION之间的任意版本。
但笔者尝试最快的安装方式是,到Github - bazelbuild/build/releases上下载对应的版本,然后使用sh脚本手动安装。比如依据刚才的配置目标,笔者需要的是Bazel3.7.2,所以下载的文件为bazel-3.7.2-installer-linux-x_.sh。
5. 配置编译build选项
官网介绍:通过运行TensorFlow源代码树根目录下的./configure配置系统build。此脚本会提示您指定TensorFlow依赖项的位置,并要求指定其他构建配置选项(例如,编译器标记)。
这一步就是选择y/N基本没啥问题,其他参考里都有贴实例。笔者需要GPU的支持,故在CUDA那一栏选择了y,其他部分如Rocm部分就是N(直接按enter也可以)。
6.开始编译
编译完成应输出
7.检查TF是否能用
3 - 踩坑记录
3.1 cuda.0在编译时不支持sm_
笔者最初选择的docker是cuda.0的,在bazel build --config=cuda //tensorflow/tools/pip_package:build_pip_package过程中出现了错误。所以之后选择了上面提到的cuda.3的docker。
3.2 问题2: numpy、TF、python版本匹配
在配置过程中,发现numpy、TF、python版本需要匹配,否则会出现错误。
4 - 启示
从源码编译Tensorflow2.6.5的过程,虽然经历了多次失败,但最终还是成功。这个过程也让我对Tensorflow的编译流程有了更深入的了解,同时也提醒我在后续的工作中要注意版本匹配问题。