1、前言

主要参考两篇博客以及很多论坛解决细节问题:

http://www.cnblogs.com/trantor/p/4570097.html

https://initialneil.wordpress.com/2015/01/11/build-caffe-in-windows-with-visual-studio-2013-cuda-6-5-opencv-2-4-9/

移植环境:Windows7 64位+原版caffe+opencv3.0。

本文主要在于移植原版caffe,而依赖库采用的是比较稳定的,而非最新版,比如未使用opencv3.1。如果想自己编译新的依赖库,可以私聊博主或者下方留言,我会根据情况看是否有必要写一个编译caffe依赖库的博客。表示依赖库用CMake编译还是蛮多问题的,折腾了一周

【PS】读者一定要注意路径问题,因此本文教程也尽量采用图片说明,且路径都标示出来了。

2、依赖库

2.1 安装boost

原始下载地址:http://sourceforge.net/projects/boost/files/boost-binaries/1.56.0/boost_1_56_0-msvc-12.0-64.exe/download

百度云盘地址:链接:http://pan.baidu.com/s/1pK7PHcn 密码:eu3v

我安装时候是默认一直下一步的,安装路径也是默认的:C:\local\boost_1_56_0

无需修改环境变量

【PS】坑人的数字卫士,建议关掉它,刚准备安装就给我把安装包删掉了。

2.2 安装opencv

原始下载地址:https://sourceforge.net/projects/opencvlibrary/files/opencv-win/3.0.0/opencv-3.0.0.exe/download

百度云盘地址:链接:http://pan.baidu.com/s/1sltOJm9 密码:19u0

参考安装文档:http://jingyan.baidu.com/article/64d05a0245aa70de55f73b12.html

第一步:提取文件

第二步:配置环境变量

添加到path中的环境变量:C:\local\opencv\build\x64\vc12\bin;C:\local\opencv\build\x86\vc12\bin

2.3 安装cuda

参考我前面安装微软版本caffe的GPU配置:http://blog.csdn.net/zb1165048017/article/details/51549105

2.4 下载其它依赖库

可以自己参考fengbingchun的博客自行配置(可能会有部分问题),也可以下载NZ的博客提供的三方包,本文采用后者

原始下载地址:https://drive.google.com/file/d/0B_G5BUend20PRnFhMUlMelFEZW8/view

云盘下载地址:链接:http://pan.baidu.com/s/1bpJtOpp 密码:dmsr

解压以后会有两个文件夹:

将第一个3rdparty拖入你想要编译caffe的目录,我这里新建了一个目录称为caffe-original

至此所有的依赖库已准备好。

3、VS配置caffe工程

3.1 下载官方caffe

官方下载地址:https://github.com/BVLC/caffe

云盘下载地址:链接:http://pan.baidu.com/s/1pLnho0N 密码:e580

直接将caffe-master内部所有文件拖入3rdparty所在文件夹中

然后在E:\caffe-original\caffe下新建一个文件夹bin

3.2 加入工程

3.2.1 新建空项目

然后修改配置管理器->活动解决方案平台

3.2.2 更改环境变量

先把属性管理器调出来:视图->其它窗口->属性管理器

然后右侧会有如下窗口

分别对debug和release添加引用文件和库目录:

① Debug下右键属性

通用属性->常规->输出目录,选择3.1中新建的bin文件夹

通用属性->c/c++->常规->附加包含目录,添加相应的包含(include)文件

通用属性->链接器->常规->附加库目录,添加相应的静态库(lib)所在文件夹

通用属性->链接器->输入->附加依赖项,添加相应的静态库(lib)文件

内容:

opencv_ts300d.lib;opencv_world300d.lib;gflagsd.lib;libglog.lib;libopenblas.dll.a;libprotobufd.lib;

libprotoc.lib;leveldbd.lib;lmdbd.lib;libhdf5_D.lib;libhdf5_hl_D.lib;Shlwapi.lib;cudart.lib;cuda.lib;

nppi.lib;cufft.lib;cublas.lib;curand.lib

② Release下右键属性

通用属性->常规->输出目录,选择3.1中新建的bin文件夹

通用属性->c/c++->常规->附加包含目录,添加相应的包含(include)文件

通用属性->链接器->常规->附加库目录,添加相应的静态库(lib)所在文件夹

上面这三个过程,直接把Debug下对应处文字拷贝过来放进去。

通用属性->链接器->输入->附加依赖项,添加相应的静态库(lib)文件

内容:

opencv_ts300.lib;opencv_world300.lib;gflags.lib;libglog.lib;libopenblas.dll.a;

libprotobuf.lib;libprotoc.lib;leveldb.lib;lmdb.lib;libhdf5.lib;

libhdf5_hl.lib;Shlwapi.lib;cudart.lib;cuda.lib;nppi.lib;cufft.lib;cublas.lib;curand.lib

3.2.3 将caffe相关文件加入工程

解决方案资源管理器->源文件->现有项中选择 E:\caffe-original\src\caffe中的所有文件

4、逐步编译三个cpp

【注】以下全是在Debug模式下操作

4.1 common.cpp

解决fopen_s不安全问题:

解决方案->caffe右键属性->配置属性->c/c++->预处理器->预处理器定义添加

_CRT_SECURE_NO_WARNINGS

修复getpid()问题,打开common.cpp,

添加头文件

#include<process.h>

注释第36行,修改内容如下:

     //pid = getpid();
#ifndef _MSC_VER pid = getpid();
#else pid = _getpid();
#endif

注释第55行,不然最后总体编译会有问题

//::google::InstallFailureSignalHandler();

检查是否修改完毕:common.cpp右键->编译,观察是否生成成功

4.2 blob.cpp(重点)

在E:\caffe-original\scripts目录下新建GeneratePB.bat,内容如下:

if exist "../src/caffe/proto/caffe.pb.h" (echo caffe.pb.h remains the same as before
) else (echo caffe.pb.h is being generated"../3rdparty/bin/protoc" -I="../src/caffe/proto" --cpp_out="../src/caffe/proto" "../src/caffe/proto/caffe.proto"
)

也可以下载:

原始下载地址:https://drive.google.com/file/d/0B_G5BUend20PRDc3bXI0YkRLaUU/view
云盘下载地址:链接:http://pan.baidu.com/s/1ge3wsMJ 密码:ikd8

运行bat,会发现在E:\caffe-original\src\caffe\proto有三个文件了,caffe.pb.cc、caffe.pb.h、caffe.proto

尝试blob.cpp右键->编译,是否能通过。

一般来说Release模式不会出问题,但是Debug模式会出现:

错误   35  error C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators' C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xutility 2132    1   caffe

困扰了很久很久,解决方案:

在C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include路径中的xutility(94kb左右的那个),右键属性,取消其只读属性,在第14行加入:

#pragma warning(disable:4996)

再编译一遍,果断成功。

4.3 solver.cpp

第11行也就是刚include完毕所有头文件的地方,添加

//port fir win32
#ifdef _MSC_VER
#define snprintf sprintf_s
#endif

尝试编译一下

5、源文件编译——layer文件夹

①解决方案资源管理器->caffe->右键源文件->添加->新建筛选器->重命名为layers

②从E:\caffe-original\src\caffe\layers随便拖一个cu文件到源文件的layers文件中,此处拖入的是absval_layer.cu

③解决方案资源管理器->caffe右键->生成依赖项->生成自定义->选择第一项cuda7.5

④对着②中拖入的absval_layer.cu右键属性->常规->项类型-CUDA C/C++(此处有几个长得很像,一定要看清,CUDA C/C++是在最后一个,否则选错了以后再编译caffe时会出现obj连接问题)

⑤源文件->layers右键->添加->现有项->添加E:\caffe-original\src\caffe\layers文件夹所有文件;

然后检查一下是不是所有的cu文件都是项类型为CUDA/C++(一般来说操作顺序对了,这一步可以忽视)

⑥打开bnll_layer.cu,注释第8行,并添加:

//const float kBNLL_THRESHOLD = 50.;
#define kBNLL_THRESHOLD 50.0

6、源文件编译——util文件夹

①解决方案资源管理器->caffe->右键源文件->添加->新建筛选器->重命名为util
②源文件->util右键->添加->现有项->添加E:\caffe-original\src\caffe\util文件夹所有文件;

③修改io.cpp的相关部分

第35行和53行中的O_RDONLY修改为O_RDONLY | O_BINARY

第1行后面添加

#if defined(_MSC_VER)
#include<io.h>
#define open _open
#endif

也就是说#include <google/protobuf/io/coded_stream.h>编程第6行了。
第44、53、67行的close(fd)全部改为_close(fd)

编译一下io.cpp看看成功了没有。

④修改math_functions.cpp内容

在第9行添加

#define __builtin_popcount __popcnt
#define __builtin_popcountl __popcnt

编译试试成功了没有。

7、源文件编译——proto文件夹

①解决方案资源管理器->caffe->右键源文件->添加->新建筛选器->重命名为proto
②源文件->util右键->添加->现有项->添加E:\caffe-original\src\caffe\proto文件夹所有文件;

8、编译caffe

①解决方案资源管理器->caffe->右键源文件->添加->现有项->选择E:\caffe-original\tools下的caffe.cpp

②解决方案资源管理器->caffe->右键生成,会出现:

>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.CppBuild.targets(364,5): warning MSB8004: Output Directory does not end with a trailing slash.  This build instance will add the slash as it is required to allow proper evaluation of the Output Directory.

③上方工具栏->生成->取消

④解决方案资源管理器->caffe->属性->配置属性->常规->输出目录改为..\bin\

⑤同样Release也需要改为..\bin\

⑥解决方案资源管理器->caffe->右键重新生成

9、余下问题解决

可见编译貌似没这么成功,在源文件->util->signal_handler.cpp和hdf5.cpp出现了问题

9.1 解决signal_handler.cpp问题

直接用我们前面微软版本的替换就行,代码如下:

#include <boost/bind.hpp>
#include <glog/logging.h>#include <signal.h>
#include <csignal>#include "caffe/util/signal_handler.h"namespace {static volatile sig_atomic_t got_sigint = false;static volatile sig_atomic_t got_sighup = false;static bool already_hooked_up = false;void handle_signal(int signal) {switch (signal) {
#ifdef _MSC_VERcase SIGBREAK:  // there is no SIGHUP in windows, take SIGBREAK instead.got_sighup = true;break;
#elsecase SIGHUP:got_sighup = true;break;
#endifcase SIGINT:got_sigint = true;break;}}void HookupHandler() {if (already_hooked_up) {LOG(FATAL) << "Tried to hookup signal handlers more than once.";}already_hooked_up = true;
#ifdef _MSC_VERif (signal(SIGBREAK, handle_signal) == SIG_ERR) {LOG(FATAL) << "Cannot install SIGBREAK handler.";}if (signal(SIGINT, handle_signal) == SIG_ERR) {LOG(FATAL) << "Cannot install SIGINT handler.";}
#elsestruct sigaction sa;// Setup the handlersa.sa_handler = &handle_signal;// Restart the system call, if at all possiblesa.sa_flags = SA_RESTART;// Block every signal during the handlersigfillset(&sa.sa_mask);// Intercept SIGHUP and SIGINTif (sigaction(SIGHUP, &sa, NULL) == -1) {LOG(FATAL) << "Cannot install SIGHUP handler.";}if (sigaction(SIGINT, &sa, NULL) == -1) {LOG(FATAL) << "Cannot install SIGINT handler.";}
#endif}// Set the signal handlers to the default.void UnhookHandler() {if (already_hooked_up) {
#ifdef _MSC_VERif (signal(SIGBREAK, SIG_DFL) == SIG_ERR) {LOG(FATAL) << "Cannot uninstall SIGBREAK handler.";}if (signal(SIGINT, SIG_DFL) == SIG_ERR) {LOG(FATAL) << "Cannot uninstall SIGINT handler.";}
#elsestruct sigaction sa;// Setup the sighub handlersa.sa_handler = SIG_DFL;// Restart the system call, if at all possiblesa.sa_flags = SA_RESTART;// Block every signal during the handlersigfillset(&sa.sa_mask);// Intercept SIGHUP and SIGINTif (sigaction(SIGHUP, &sa, NULL) == -1) {LOG(FATAL) << "Cannot uninstall SIGHUP handler.";}if (sigaction(SIGINT, &sa, NULL) == -1) {LOG(FATAL) << "Cannot uninstall SIGINT handler.";}
#endifalready_hooked_up = false;}}// Return true iff a SIGINT has been received since the last time this// function was called.bool GotSIGINT() {bool result = got_sigint;got_sigint = false;return result;}// Return true iff a SIGHUP has been received since the last time this// function was called.bool GotSIGHUP() {bool result = got_sighup;got_sighup = false;return result;}
}  // namespacenamespace caffe {SignalHandler::SignalHandler(SolverAction::Enum SIGINT_action,SolverAction::Enum SIGHUP_action):SIGINT_action_(SIGINT_action),SIGHUP_action_(SIGHUP_action) {HookupHandler();
}SignalHandler::~SignalHandler() {UnhookHandler();
}SolverAction::Enum SignalHandler::CheckForSignals() const {if (GotSIGHUP()) {return SIGHUP_action_;}if (GotSIGINT()) {return SIGINT_action_;}return SolverAction::NONE;
}// Return the function that the solver can use to find out if a snapshot or
// early exit is being requested.
ActionCallback SignalHandler::GetActionFunction() {return boost::bind(&SignalHandler::CheckForSignals, this);
}}  // namespace caffe

9.2 解决hdf5.cpp问题

直接用我们前面微软版本的替换就行,代码如下:

#include "caffe/util/hdf5.hpp"#include <string>
#include <vector>namespace caffe {// Verifies format of data stored in HDF5 file and reshapes blob accordingly.
template <typename Dtype>
void hdf5_load_nd_dataset_helper(hid_t file_id, const char* dataset_name_, int min_dim, int max_dim,Blob<Dtype>* blob) {// Verify that the dataset exists.CHECK(H5LTfind_dataset(file_id, dataset_name_))<< "Failed to find HDF5 dataset " << dataset_name_;// Verify that the number of dimensions is in the accepted range.herr_t status;int ndims;status = H5LTget_dataset_ndims(file_id, dataset_name_, &ndims);CHECK_GE(status, 0) << "Failed to get dataset ndims for " << dataset_name_;CHECK_GE(ndims, min_dim);CHECK_LE(ndims, max_dim);// Verify that the data format is what we expect: float or double.std::vector<hsize_t> dims(ndims);H5T_class_t class_;status = H5LTget_dataset_info(file_id, dataset_name_, dims.data(), &class_, NULL);CHECK_GE(status, 0) << "Failed to get dataset info for " << dataset_name_;switch (class_) {case H5T_FLOAT:// In VC++ declaring and initializing variables in case statement without// curly braces (new scope), cause compiler error C2360// https://msdn.microsoft.com/en-us/library/61af7cx3.aspx{LOG_FIRST_N(INFO, 1) << "Datatype class: H5T_FLOAT";break;}case H5T_INTEGER:{LOG_FIRST_N(INFO, 1) << "Datatype class: H5T_INTEGER";break;}case H5T_TIME:{LOG(FATAL) << "Unsupported datatype class: H5T_TIME";}case H5T_STRING:{LOG(FATAL) << "Unsupported datatype class: H5T_STRING";}case H5T_BITFIELD:{LOG(FATAL) << "Unsupported datatype class: H5T_BITFIELD";}case H5T_OPAQUE:{LOG(FATAL) << "Unsupported datatype class: H5T_OPAQUE";}case H5T_COMPOUND:{LOG(FATAL) << "Unsupported datatype class: H5T_COMPOUND";}case H5T_REFERENCE:{LOG(FATAL) << "Unsupported datatype class: H5T_REFERENCE";}case H5T_ENUM:{LOG(FATAL) << "Unsupported datatype class: H5T_ENUM";}case H5T_VLEN:{LOG(FATAL) << "Unsupported datatype class: H5T_VLEN";}case H5T_ARRAY:{LOG(FATAL) << "Unsupported datatype class: H5T_ARRAY";}default:{LOG(FATAL) << "Datatype class unknown";}}vector<int> blob_dims(dims.size());for (int i = 0; i < dims.size(); ++i) {blob_dims[i] = dims[i];}blob->Reshape(blob_dims);
}template <>
void hdf5_load_nd_dataset<float>(hid_t file_id, const char* dataset_name_,int min_dim, int max_dim, Blob<float>* blob) {hdf5_load_nd_dataset_helper(file_id, dataset_name_, min_dim, max_dim, blob);herr_t status = H5LTread_dataset_float(file_id, dataset_name_, blob->mutable_cpu_data());CHECK_GE(status, 0) << "Failed to read float dataset " << dataset_name_;
}template <>
void hdf5_load_nd_dataset<double>(hid_t file_id, const char* dataset_name_,int min_dim, int max_dim, Blob<double>* blob) {hdf5_load_nd_dataset_helper(file_id, dataset_name_, min_dim, max_dim, blob);herr_t status = H5LTread_dataset_double(file_id, dataset_name_, blob->mutable_cpu_data());CHECK_GE(status, 0) << "Failed to read double dataset " << dataset_name_;
}template <>
void hdf5_save_nd_dataset<float>(const hid_t file_id, const string& dataset_name, const Blob<float>& blob,bool write_diff) {int num_axes = blob.num_axes();hsize_t *dims = new hsize_t[num_axes];for (int i = 0; i < num_axes; ++i) {dims[i] = blob.shape(i);}const float* data;if (write_diff) {data = blob.cpu_diff();} else {data = blob.cpu_data();}herr_t status = H5LTmake_dataset_float(file_id, dataset_name.c_str(), num_axes, dims, data);CHECK_GE(status, 0) << "Failed to make float dataset " << dataset_name;delete[] dims;
}template <>
void hdf5_save_nd_dataset<double>(hid_t file_id, const string& dataset_name, const Blob<double>& blob,bool write_diff) {int num_axes = blob.num_axes();hsize_t *dims = new hsize_t[num_axes];for (int i = 0; i < num_axes; ++i) {dims[i] = blob.shape(i);}const double* data;if (write_diff) {data = blob.cpu_diff();} else {data = blob.cpu_data();}herr_t status = H5LTmake_dataset_double(file_id, dataset_name.c_str(), num_axes, dims, data);CHECK_GE(status, 0) << "Failed to make double dataset " << dataset_name;delete[] dims;
}string hdf5_load_string(hid_t loc_id, const string& dataset_name) {// Get size of datasetsize_t size;H5T_class_t class_;herr_t status = \H5LTget_dataset_info(loc_id, dataset_name.c_str(), NULL, &class_, &size);CHECK_GE(status, 0) << "Failed to get dataset info for " << dataset_name;char *buf = new char[size];status = H5LTread_dataset_string(loc_id, dataset_name.c_str(), buf);CHECK_GE(status, 0)<< "Failed to load int dataset with name " << dataset_name;string val(buf);delete[] buf;return val;
}void hdf5_save_string(hid_t loc_id, const string& dataset_name,const string& s) {herr_t status = \H5LTmake_dataset_string(loc_id, dataset_name.c_str(), s.c_str());CHECK_GE(status, 0)<< "Failed to save string dataset with name " << dataset_name;
}int hdf5_load_int(hid_t loc_id, const string& dataset_name) {int val;herr_t status = H5LTread_dataset_int(loc_id, dataset_name.c_str(), &val);CHECK_GE(status, 0)<< "Failed to load int dataset with name " << dataset_name;return val;
}void hdf5_save_int(hid_t loc_id, const string& dataset_name, int i) {hsize_t one = 1;herr_t status = \H5LTmake_dataset_int(loc_id, dataset_name.c_str(), 1, &one, &i);CHECK_GE(status, 0)<< "Failed to save int dataset with name " << dataset_name;
}int hdf5_get_num_links(hid_t loc_id) {H5G_info_t info;herr_t status = H5Gget_info(loc_id, &info);CHECK_GE(status, 0) << "Error while counting HDF5 links.";return info.nlinks;
}string hdf5_get_name_by_idx(hid_t loc_id, int idx) {ssize_t str_size = H5Lget_name_by_idx(loc_id, ".", H5_INDEX_NAME, H5_ITER_NATIVE, idx, NULL, 0, H5P_DEFAULT);CHECK_GE(str_size, 0) << "Error retrieving HDF5 dataset at index " << idx;char *c_str = new char[str_size+1];ssize_t status = H5Lget_name_by_idx(loc_id, ".", H5_INDEX_NAME, H5_ITER_NATIVE, idx, c_str, str_size+1,H5P_DEFAULT);CHECK_GE(status, 0) << "Error retrieving HDF5 dataset at index " << idx;string result(c_str);delete[] c_str;return result;
}}  // namespace caffe

编译这两个cpp试试,直接对着cpp右键编译。

9.3 解决steam问题

出现了问题

错误   20  error C4703: 使用了可能未初始化的本地指针变量“stream”   e:\caffe-original\src\caffe\layers\base_data_layer.cpp  101 1   caffe

解决方法
解决方案资源管理器->caffe->右键属性->配置属性->C/C++->SDL检查,选择“否”

9.4 重新编译

解决方案资源管理器->caffe->右键生成

9.5 最终问题

可以发现生成成功了,但是ctrl+F5却发现缺少dll

好吧,dll一般来说可以在E:\caffe-original\3rdparty\bin下找到,但是可能不全,这里我提供一下下载地址

链接:http://pan.baidu.com/s/1jI7AoRk 密码:9teo

宿舍笔记本出现了libgfortran-3.dll丢失问题,读者电脑如果无此问题可以无需下载:

链接:http://pan.baidu.com/s/1bpr92hh 密码:de8q

解压以后得到的dll全部丢到C:\Windows\System32里面就行了,好像丢C:\Windows\SysWOW64这里面没用貌似

然后ctrl+F5,看到了心满意足的答案。。。。

【caffe-windows】Linux至Windows平台的caffe移植相关推荐

  1. windows linux 融合,Windows和Linux的设备驱动框架的对比融合研究

    摘要:把驱动框架分为三层,针对各层在Windows和Linux中的实现方法的不同,对Windows和Linux的设备驱动框架进行对比研究.从接口函数,应用程序访问驱动程序的路径,驱动程序具体实现及安装 ...

  2. linux端口转发到windows,Linux及Windows基于工具的端口转发

    Linux及Windows基于工具和命令的端口转发配置 wget http://www.boutell.com/rinetd/http/rinetd.tar.gz&&tar -xvf ...

  3. 双用户windows linux系统,Windows与Linux合二为一?终于能在windows上运行Linux了!

    原标题:Windows与Linux合二为一?终于能在windows上运行Linux了! 目前在PC端操作系统市场份额中,微软旗下的windows系统占据超过50%的比例. 作为微软旗下发布的产品之一, ...

  4. windows linux mysql_linux/windows环境mysql数据库安装与使用

    MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用 ...

  5. 设置linux引导windows,linux与windows双引导设置【原创】

    最近看到很多朋友问如何实现linux 与 windows 双引导,usen在此向大家介绍一下我的方法,以供大 家参考学习.如你看了,有疑问或使用时有问题,请留言. 关于linux 与windows 双 ...

  6. 深度学习模型之各种caffe版本(Linux和windows)的网址

    网:http://caffe.berkeleyvision.org/ 1.最原始的最开始版本:伯克利BVLC版 https://github.com/BVLC/caffe 主要在Linux上运行,有m ...

  7. anki ios android 同步,让记忆更轻松的Anki,支持Windows,Linux,iOS,Android平台

    Anki介绍 Anki是一个记忆辅助软件,它可以让记忆过程变得更加轻松容易.因为,相比传统方法他更加高效更加智能,利用它你可以大大降低你的学习时间,或者你可以在同样长的时间内学习更多的内容. 任何人如 ...

  8. cmake windows linux,在Windows中像Linux里一样使用CMake和make

    1. 安装GCC环境 1.1 安装MinGW(Minimalist GNU for Windows) 首先下载MinGW,并安装.安装完成之后运行MinGW Installer.界面如下.勾选自己需要 ...

  9. 蓝牙鼠标windows linux,关于windows linux双系统共用蓝牙鼠标的教程

    Linux(例如Ubuntu和Fedora)和Windows 10 双系统,将蓝牙鼠标连接到系统并在另一个系统上重新启动后,必须将鼠标卸下并重新连接,这是有问题的. 互联网上提供的解决方案是像我的计算 ...

  10. windows linux 并发,Windows/Linux安装压力测试工具siege

    Siege是一款高性能的Http压力测试工具. Siege支持身份验证.cookies.http.https和ftp协议. Linux安装Siege 如果要支持https,需要先下载安装openssl ...

最新文章

  1. tableau实战系列(三十九)-教你如何优雅的做图表展示-南丁格尔玫瑰图
  2. JavaScript的表单事件
  3. 2021 三月1日雅思口语考试反思
  4. matlab超出矩阵索引维度_搜你想看“头条搜索”网页版上线 搜索引擎迎来新玩家...
  5. linux c/c++ 文件是否存在
  6. 《软件需求分析(第二版)》第 14 章——需求管理的原则和实践 重点部分总结
  7. Screen命令让Linux shell在后台运行
  8. php百度地图地址解析失败,javascript - vue中使用百度地图 提示无法解析
  9. 【转】读《精进》,好书啊
  10. 如何使用十六进制颜色值
  11. android下载模块封装,AndroidStudio 3.0 NDK开发2-AAR模块封装
  12. avalon 笔记---Mr.wing
  13. 线材下料优化python算法_python实现最优化算法
  14. linux scp 拷贝文件
  15. upc 6605: 所罗门王的宝藏(矩阵行列规律)
  16. echarts地图api series_ECharts地图绘制和钻取简易接口详解
  17. Pycharm提示No Python interpreter selected怎么解决
  18. 《八股文》20道Redis面试题
  19. cf #818 Div.2(A~C)
  20. 拓嘉辰丰电商:如何投诉拼多多商家一直不发货

热门文章

  1. C语言结构和高二的知识,c语言基础知识复习.pdf
  2. 深度学习之基于CNN和VGG19实现灵笼人物识别
  3. python爬虫取腾讯视频评论
  4. 计算机术语桢什么意思,请问电脑丢帧严重的“丢帧”是啥意思哦?
  5. mysql 乐观锁_使用Mysql乐观锁解决并发问题
  6. 个人网站备案起名_郑州诚信个人商标注册电话
  7. 『安卓』安卓开发基础--基本控件
  8. TensorFlow 2.0快速上手指南12条:“Keras之父”亲授 | 高赞热贴
  9. mac中安装activeMQ
  10. HTML中的国家名称代码表