1. 代码清理
1. 文件目录清理
.
├── [data]
│ └── [labels]
├── [examples]
├── [include]
├── [src]
└── Makefile
只保留./data/labels目录下所有文件与其余目录下的*.c,*.h文件
2. 条件编译清理
由于Darknet有针对GPU的优化与使用了OpenCV,可以先排除掉这一部分,让主体代码逻辑更清楚。这里使用unifdef工具来删去相关代码。
apt-get install unifdef
安装unifdef工具包
unifdef -K -U CONFIG_XXXX /path/to/file
这里,-K 是防止 unifdef 处理一些带常数的条件编译,比如 #if 0。-U 就是指定某个宏是 undefined。
#!/bin/bash
filelist=`find . -name *.c -o -name *.h`
for file in $filelist
do
unifdef -K -U GPU CUDNN OPENCV $file > $file.out
cmp --silent $file $file.out || cp $file.out $file
rm -f $file.out
done
编译测试一下,看否精简得有问题
3. 文件结构归一
将 .c,.h 文件归一到一个文件夹下面,写个Makefile
EXEC = darknet
CC = gcc
CFLAGS = -Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors
LDFLAGS = -lm -pthread
OBJS = gemm.o utils.o cuda.o deconvolutional_layer.o convolutional_layer.o list.o image.o activations.o im2col.o col2im.o blas.o crop_layer.o dropout_layer.o maxpool_layer.o softmax_layer.o data.o matrix.o network.o connected_layer.o cost_layer.o parser.o option_list.o detection_layer.o route_layer.o upsample_layer.o box.o normalization_layer.o avgpool_layer.o layer.o local_layer.o shortcut_layer.o logistic_layer.o activation_layer.o rnn_layer.o gru_layer.o crnn_layer.o demo.o batchnorm_layer.o region_layer.o reorg_layer.o tree.o lstm_layer.o l2norm_layer.o yolo_layer.o iseg_layer.o \
captcha.o lsd.o super.o art.o tag.o cifar.o go.o rnn.o segmenter.o regressor.o classifier.o coco.o yolo.o detector.o nightmare.o instance-segmenter.o darknet.o
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(OBJS) -o $(EXEC) $(LDFLAGS)
$(OBJS):
$(CC) -c $(CFLAGS) $*.c -o $*.o
.PHONY: clean
clean:
rm -rf $(EXEC) $(OBJS)
make编译一下,执行测试命令(没有权重文件先在官网下载好):
./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg
可以看到结果没问题,至于预测时间嘛,也是相当感人的。。。。。(主频4.2GHz情况下,3分钟)
这是清理过后源代码,欢迎Watch、Star、Fork三连:
https://github.com/SimpleDoger/Darknet_CPU_Only(这个版本是做了指针和对象错误修复过后的版本,并测试过与原版执行结果相同)
2. 创建VS2013工程
接下来即便是耗费大力气为什么都要推到Windows系统上呢,因为Windows系统上有宇宙最强IDE加持。。。能事半功倍
1. 代码修复
由于MSVC与GCC编译的差异,在GCC下能编译通过,但是在MSVC下报错。主要报错的地方有:
- 相关头文件未找到(除了pthread.h,其余都能找到替代)
- what_time_is_it_now()函数实现修复
- 指针和对象错误(
这个应该属于原作者书写不规范,遗留下的bug,虽然不严格的gcc编译能通过。刚刚看了下原作者简历,拿Vim撸的。。。。)- 清理掉文件:captcha.c、lsd.c、super.c、art.c、tag.c、cifar.c、go.c、rnn.c、segmenter.c、regressor.c、classifier.c、coco.c、yolo.c、nightmare.c、instance-segmenter.c。并备注掉darknet.c里面相关调用代码。这些算是对Darknet框架应用层上的东西了,和detector.c完成功能同级。
1) what_time_is_it_now()函数实现修复
double what_time_is_it_now()
{
double time_now = clock() / 1000.0;
return time_now;
}
2)关于net报错的地方,将对象改为指针
2. 添加VC版pthread支持(已废除)
后来发现在运行的时候有动态内存分配溢出,会导致后面的calloc失败?不知道,反正移除了过后能正常运行了。很诡异,在有调试器加持的情况下没问题。。。
Pre-built.2\dll\x86\pthreadVC2.dll 到程序生成目录
Pre-built.2\lib\x86\pthreadVC2.lib 到程序生成目录
Pre-built.2\include\pthread.h 到工程目录
Pre-built.2\include\sched.h 到工程目录
Pre-built.2\include\semaphore.h 到工程目录
工程包含对应头文件
- 修改pthread.h
在42行添加:
#pragma comment(lib,"pthreadVC2.lib")
修改300行为:
#include "sched.h"
2. 移除pthread相关代码
pthread相关代码经过分析主要用在了数据加载上。通过多线程加载图片,标签数据源到内存,相关函数包含在swag.c、voxel.c、writing.c、attention.c、compare.c、data.c、detector.c文件里面。
终于可以运行调试了,Bingo~
借助强大的IDE,能很方便的生成函数调用逻辑关系图:
代码的分析将在随后的文章详解
-----逃-----