caffe使用工具 caffe 编译后生成动态链接库 libcaffe.so
。使用caffe时,在main.cpp中调用相应API,编译时包含对应的头文件,链接时加入 libcaffe.so
。如此才是一个完整的caffe应用。
在tools/中就是一些调用libcaffe.so
的工具源码。
前面提到过,caffe.bin工具由4个功能:
1 2 3 4 ./caffe.bin train ./caffe.bin test ./caffe.bin device_query ./caffe.bin time
从tools/caffe.cpp
中看看是如何实现传递不同的参数,执行不同的功能。
首先定义一个caffe命令注册表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 typedef int (*BrewFunction) () ;typedef std ::map <caffe::string , BrewFunction> BrewMap;BrewMap g_brew_map; #define RegisterBrewFunction(func) \ namespace { \class __Registerer_ ##func { \ public : \ __Registerer_##func() { \ g_brew_map[#func] = &func; \ } \ }; \ __Registerer_##func g_registerer_##func; \ }
device_query命令: 1 2 3 4 5 6 7 8 9 10 11 int device_query () { LOG(INFO) << "Querying GPUs " << FLAGS_gpu; vector <int > gpus; get_gpus(&gpus); for (int i = 0 ; i < gpus.size(); ++i) { caffe::Caffe::SetDevice(gpus[i]); caffe::Caffe::DeviceQuery(); } return 0 ; } RegisterBrewFunction(device_query);
train命令 1 2 int train () {...}RegisterBrewFunction(train);
test命令 1 2 int test () {...}RegisterBrewFunction(test);
time命令 1 2 int time () {...}RegisterBrewFunction(time);
上述将4条命令加入注册表。
从注册表中取对应的命令:
1 2 3 4 5 static BrewFunction GetBrewFunction (const caffe::string & name) { if (g_brew_map.count(name)) { return g_brew_map[name]; } else {...} }
从main函数中调用:
1 2 3 4 5 6 7 8 9 10 11 12 int main (int argc, char ** argv) { ... gflags::SetUsageMessage("command line brew\n" "usage: caffe <command> <args>\n\n" "commands:\n" " train train or finetune a model\n" " test score a model\n" " device_query show GPU diagnostic information\n" " time benchmark model execution time" ); ... return GetBrewFunction(caffe::string (argv[1 ]))(); }
如上实现了在caffe.bin工具中执行不同的命令。
还有其他工具:特征提取,图像格式转换,计算图像均值,等等。
编写自己的工具 编写自己的工具帮助理解 caffe 框架和操作。
caffe中的GPU实现 其实caffe不需要手动编写CUDA程序,而是直接使用cuBLAS
实现数学计算,相当于CPU端的OpenBLAS
和MKL
计算库。
上述是从数学计算角度,而对于DL中常见算子,如卷积,下采样等,在cuDNN
中都已实现。