libtorch 报错与解决
1.error: conversion from ‘at::TensorAccessor<float, 2ul, at::DefaultPtrTraits, long int>’ to non-scalar type ‘at::Tensor’ requested
torch::Tensor result_data = result_.accessor<float,2>();// torch::Tensor result_data = result_.cpu().accessor<float,2>();
定位到代码中的语句
torch::Tensor result_data = result_.accessor<float,2>();
各种试,result是二维的啊,是float的啊!!!
转到了cpu了啊!!
奔溃~~,我看别人也是这么写的啊!!
例子:
torch::Tensor one = torch::randn({9,6});
auto foo_one=one.accessor<float,2>();
for(int i=0,sum=0;i<foo_one.size(0);i++)
for(int j=0;j<foo_one.size(1);j++)
sum+=foo_one[i][j];
然后的然后,我把 torch::Tensor result_data = result_.accessor<float,2>();改成
auto result_data = result_.accessor<float,2>();
编译通过了!!!!ヾ(。`Д´。)!!!!!
这个问题找了我半个小时多!!!!原来已经不是torch::Tensor类型了,需要用auto啊!!
2. pytorch转到libtorch显存偏多问题
一般用测试代码直接加两句话就可以转成功libtorch模型
output = model(image)
traced_script_module = torch.jit.trace(model, image)
traced_script_module.save("/data_2/v3+resnet.pt")
就是这个测试代码流程一般就是定义模型,加载模型,数据处理,模型推理,后处理这些部分组成
model = DeepLab(num_classes=num_classes_,
backbone=backbone_,
output_stride=output_stride_,
sync_bn=sync_bn_,
freeze_bn=freeze_bn_)
model = model.cuda()
checkpoint = torch.load(model_path)
model.load_state_dict(checkpoint['state_dict'])
del checkpoint
dataload_test = make_data_loader_my_test(path_txt,crop_size,batch_size)
for i, sample in enumerate(dataload_test):
print(i)
image = sample[0]
if cuda:
image = image.cuda()
with torch.no_grad():
model = model.eval() ####重要!! 测试的时候一定要加上 要不然bn层还会重新计算 是test模式就直接用
output = model(image)
traced_script_module = torch.jit.trace(model, image)
traced_script_module.save("/data_2/v3+resnet.pt")
break
pred = output.data.cpu().numpy()
pred = np.argmax(pred, axis=1)
一般就是上面的这段代码,在pytorch端一点问题都没有,可以在libtorch端显存变2倍啊!pytorch端900M,libtorch端1800M!!
几天后,然后对比了之前没有问题的脚本,实验了一下果真可以!多了的话如下:
model = DeepLab(num_classes=num_classes_,
backbone=backbone_,
output_stride=output_stride_,
sync_bn=sync_bn_,
freeze_bn=freeze_bn_)
for param in model.parameters():
param.requires_grad = False
model = model.cuda()
原来转libtorch需要自己加上这句话啊!!!
3
ValueError: Auto nesting doesn't know how to process an input object of type int. Accepted types: Tensors, or lists/tuples of them
在pytorch1.1 cuda10上是可以的,但是在pytorch1.0 cuda8上面就报上面的错误。trace的时候
traced_script_module = torch.jit.trace(self.dla, x)
折腾几个小时已经解决,把class IDAUP的forward
def forward(self, layers, startp, endp):
startp, endp是int形的,转成tensor,再在forward里面解析出int
endp = endp.cpu().numpy()[0]
解决方案如上,在此记录一下!
https://github.com/xi11xi19/CenterNet2TorchScript/issues/5
4 libtorch 运行时间问题
一般情况下,我们用c++或者opencv自带的函数统计函数运行时间
auto t_3 = std::chrono::steady_clock::now();
// 一段代码
auto ttt = std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::steady_clock::now() - t_3).count();
std::cout << "-step3--(--)consume time="<<ttt<<"ms"<<std::endl;
可是一个很诡异的现象是在一个函数中我调用同一个libtorch函数torch::nonzero(ind_mask.squeeze(0));,刚进来的时候耗时50ms,然后该函数调用torch::nonzero(ind_mask.squeeze(0));5次,只有第一次的时候显示50ms,
然后后面4次0ms,下张图片进来还是这个现象。。。这么说每张都是这样了??
找了很久很久原因。。。未果。。然后去问同事,同事告诉我需要加cuda同步
#include<cuda.h>
#include<cuda_runtime.h>
cudaDeviceSynchronize();
auto t_3 = std::chrono::steady_clock::now();
// 一段代码
auto ttt = std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::steady_clock::now() - t_3).count();
std::cout << "-step3--(--)consume time="<<ttt<<"ms"<<std::endl;
--------------------------2021年07月01日09:54:39 更新----
cudaDeviceSynchronize();
这个放置的位置有问题把。这句话应该放在结束时间之前!
正确的代码如下:
#include<cuda.h>
#include<cuda_runtime.h>
auto t_3 = std::chrono::steady_clock::now();
// 一段代码
cudaDeviceSynchronize();//这句话应该放在结束时间之前!
auto ttt = std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::steady_clock::now() - t_3).count();
std::cout << "-step3--(--)consume time="<<ttt<<"ms"<<std::endl;
如此,就可以了!!
但是后面又遇到问题了,就是我需要看哪个函数耗时,然后把每个函数时间运行前运行后统计,然后发现总时间大于各个函数时间运行之和,而且是大于2倍!!!
同事说我是不是有些函数没有统计到?不是的,我都统计了,然后我再各个函数里面刚开始加上cudaDeviceSynchronize();也不行。。。。
目前还没有即=解决,先在这里记录一下!!!。。
解决了,jiamin让我在
auto out_center = process_centernet(input_tensor);后面加
sleep(1);
一开始是这样的:
cudaDeviceSynchronize();
auto t_2 = std::chrono::steady_clock::now();
auto out_center = process_centernet(input_tensor);///////////////////////////////
// sleep(1);
torch::Tensor out_ct_hm = std::get<0>(out_center);
torch::Tensor out_wh = std::get<1>(out_center);
torch::Tensor out_cnn_feature = std::get<2>(out_center);
ttt = std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::steady_clock::now() - t_2).count();
std::cout << "-step2--centernet consume time="<<ttt<<"ms"<<std::endl;
统计出来的是23ms左右
然后就了sleep(1)就变成了1089ms这样子,!!!!说还有统计时间的先提前出来了。加 cudaDeviceSynchronize();也没有用。
然后用cuda的统计函数,
#include<cuda.h>
#include<cuda_runtime.h>
#include <cuda_runtime_api.h>
cudaEvent_t e_start, e_stop;
//创建事件
cudaEventCreate(&e_start);
cudaEventCreate(&e_stop);
//记录事件,开始计算时间
cudaEventRecord(e_start, 0);
// 运行代码
//记录结束时事件
cudaEventRecord(e_stop, 0);// 0 代表CUDA流0
//等待事件同步后
cudaEventSynchronize(e_stop);
//计算对应的时间,评估代码性能
float elapsedTime;
cudaEventElapsedTime(&elapsedTime, e_start, e_stop);
std::cout << " --##cuda center all time = ##-- ="<<elapsedTime<<"s"<<std::endl;
这个统计出来就是89ms!!!原来还是用cuda统计函数好使啊!