问题:make -jN // 多任务并行化
出错了!!!
只有一个原因,那就是 makefile 写错了。
当然,因为代码原因不算此列。
TIPS:定位 make 错误
可以先用 make -jN 快速得到 error 的地方,出现错误之后,再用 make 查看具体错误在哪里。
在这里列出几种出错的原因总结:
(1)依赖缺失/缺少中间结果
1 2 3 4 5 6 7 8 9 10 |
# Makefile .PHONY : all all : t1 t2 @echo $@ done. t2 : cp t1 $@ t1 : sleep 1 touch $@ |
直接 make 会成功,顺序执行 t1 -> t2 -> all。但用 make -j4 会失败。这是因为 Makefile 中 t2 并不依赖于 t1,所以 t1 / t2 并行执行,但 t2 实际上需要 t1 的结果。故可以修改成如下:
1 2 3 4 5 6 7 8 9 10 |
# Makefile .PHONY : all all : t1 t2 @echo $@ done. t2 : <span style="color: #ff0000;"><strong>t1</strong></span> cp t1 $@ t1 : sleep 1 touch $@ |
(2)不同目标交错执行/临界资源访问问题
这个原因如果对多进程/多线程编程有点了解和感悟,对多进程资源访问机制有所了解,就不难理解这个原因是怎么发生的。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Makefile .PHONY : all all : t1 t2 cat t1 t2 > $@ t2 : echo test from $@ > $(TEMP_FILE) sleep 2 cat $(TEMP_FILE) > $@ t1 : sleep 1 echo test from $@ > $(TEMP_FILE) cat $(TEMP_FILE) > $@ |
直接 make 会出现:
1 2 3 |
less all test from t1 test from t2 |
而用 make -j4 会出现:
1 2 3 |
less all test from t1 <strong><span style="color: #ff0000;">test from t1</span></strong> |
这是对 temp_file 的交叉访问导致的,修改与(1)一样,建立一个依赖避免 t1 / t2 的并发问题即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Makefile .PHONY : all all : t1 t2 cat t1 t2 > $@ t2 : <span style="color: #ff0000;"><strong>t1</strong></span> echo test from $@ > $(TEMP_FILE) sleep 2 cat $(TEMP_FILE) > $@ t1 : sleep 1 echo test from $@ > $(TEMP_FILE) cat $(TEMP_FILE) > $@ |
(3)代码出现问题
例如 opencv 与 opencv_contrib 一起编译时出现命名空间问题导致编译不通过,在 ver 3.4.4 & ver 4.0.0 遇到过这个问题,是关于 opencv_contrib/cvv/…/qtutil 相关文件的。
解决办法:在某文件中添加了命名空间的代码。
1 |
using namespace cv; |