PyTorch多卡/多GPU/分布式DPP:
基本概念: https://blog.csdn.net/hxxjxw/article/details/119606518、 https://zhuanlan.zhihu.com/p/602305591
多卡:
Path语法:
路径操作语法,可以直接用 / 。这个cwd是显示你调用他所在的目录
script_dir = Path.cwd()
print(type(script_dir)) # <class 'pathlib.PosixPath'>
output_dir = script_dir / args.output_dir
# /home/jiahao_su/LIMPQ-main/indicators_pretraining
# /home/jiahao_su/LIMPQ-main/indicators_pretraining/out
创建directory,最简便:
output_dir.mkdir(exist_ok=True)
参数 exist_ok=True 表示如果目录已经存在,则不会抛出异常,也不会覆盖现有的目录。如果目录不存在,则会创建该目录。这个参数通常用于避免在创建目录时因目录已存在而引发异常。
modules、state_dict()区分
model.modules()
方法
返回一个生成器,该生成器遍历模型的所有模块,包括模型本身和它的子模块,以及子模块的子模块,依此类推。每次迭代返回一个模块对象。
model.state_dict()
方法返回一个字典,其中包含了模型的所有参数(权重和偏置项)以及每个参数对应的键(通常是参数的名称)在PyTorch中,直接修改model.state_dict()并不会改变模型的参数值,因为model.state_dict()返回的是一个字典的副本,而不是原始的参数字典。
用法:model.state_dict().keys() / .items() / .values()
只能用load_state_dict
来加载,我们每次只给一个赋值,strict要设置成false,因为他会自动核实能否对上。
key_index = list(model.state_dict().keys())
for item, (key, value) in enumerate(checkpoint.items()):
model_key = key_index[item]
# logger.info(model.state_dict()[model_key])
# logger.info("value is %s", value)
# model.state_dict()[model_key] = value
model.load_state_dict({model_key: value}, strict=False)
cuda版本不对应引发的fault
版本号向下兼容 nvidia cuda>=cuda running>=torch cuda
报错:segmentation fault
现象:
nvidia-smi 给的 cuda号为 12.0
nvcc -V 给的是11.7
我选的toch是11.8
解决:
torch改成11.7版本的
高版本一般是要兼容低版本的,我们装torch的时候要保证<= cuda running (nvcc -V)
非常容易犯的BUG
正确:
w.data[idx]=a
w[idx].data.copy_(a)
错误:
w[idx].data = a
但是访问的时候两种都能访问成功
logger
(function) def getLogger(name: str | None = None) -> Logger
Return a logger with the specified name, creating it if necessary.
If no name is specified, return the root logger.
.all()
x.all()
函数返回一个布尔张量,如果张量中的所有元素都为非零值,则返回 True,否则返回 False
蚌埠住了:一直写x.all() >= 0
然后一直不报错,真的搞笑。
import torch
x = torch.tensor([2.0, -1])
assert (x >= 0.0).all()
np.prod()
np.prod(kernel_dims)
:这部分计算了卷积核的大小。kernel_dims 是卷积核的维度,通常是一个三元组 (height, width, depth),表示卷积核的高度、宽度和深度(或通道数)。np.prod() 函数计算了这个三元组中所有元素的乘积,即卷积核的大小(或称为卷积核的参数数量)
prod 接受的是 tensor
print(torch.prod(torch.tensor([*(y.shape)])) - torch.count_nonzero(y))
推导式
# 适用于字典 先遍历外层outer AvgO.items()
final_AvgO = {outerkey : {innerkey: value / len(test_loader) for innerkey, value in outervalue.items()}
for outerkey, outervalue in AvgO.items()}
# 列表 先遍历的是layer_name_list,然后在每个layer_name_list中,对应的bit_width_list也被遍历
problem += lpSum([(layer_wise_act[layer_name_list[i]][str(bit_width_list[k])])
* variable[f"l{i}_a{k}"] for i in range(len(layer_name_list)) for k in range(len(bit_width_list))])
problem += lpSum([variable[f"l{i}_a{k}"] * Proxy_E[layer_name_list[i]][k] for i in range(
len(layer_name_list)) for k in range(len(bit_width_list))]) <= cons
SumE_perL = {i : sum([Proxy_E[key][i - 2] for key in Proxy_E.keys()]) for i in range(2, 7, 1)}
SumE_perL_values = list(SumE_perL.values())[:len(bit_width_list)]
cons = sum(SumE_perL_values) / len(SumE_perL_values)
Proxy_E = {outerkey: [value * bit_ops[idx] * 0.9 for _, value in outervalue.items()]
for idx, (outerkey, outervalue) in enumerate(AvgO.items())}
print(“*”*80, [0] * 4 )
list的内置方法
Average = sum(my_list) / len(my_list)
list1.extend(list2) # append只能加一个,extend(iter)
还有一些混个面熟吧
model._modules.items():
for k, v in model._modules.items():
print(k)
merge
expand
layer1
layer2
layer3
layer4
layer5
classifier
repre
def extra_repr(self) -> str:
return f"L:{self.L}, T:{self.T}"
def __repr__(self):
return f"L:{self.L}, T:{self.T}"
BUG
重复添加相同列表(tmp)到 gap 中:在Python中,列表是可变对象。当你将 tmp 添加到 gap 时,实际上是在每次迭代中都添加了对同一个列表的引用。因此,gap 中的所有元素都指向同一个列表,最终这个列表会变成所有迭代后 tmp 的最终状态
gap = []
tmp = []
for i in range(1, 5, 1):
gap.append(tmp)
for j in range(len(value[0])):
x = value[4 - i][j] - value[5 - i][j]
if len(tmp) == len(value[0]):
tmp[j] += x
else:
tmp.append(x)
print(tmp)
错误再现:
snn_optimizer = torch.optim.SGD(model.parameters(), args.aware_lr, momentum=args.momentum, weight_decay=args.weight_decay)
Expand_as + Repeat_interleave
好用
import torch
import torch.nn as nn
y = torch.rand([2, 3, 6])
x = torch.tensor([2, 4, 5]).view(1, -1, 1)
print(x.shape)
print(y.shape)
x = x.expand_as(y)
print(x.shape)
print(x[:, 1, :])
#tensor([[4, 4, 4, 4, 4, 4],
# [4, 4, 4, 4, 4, 4]])
print(x[:, 0, :])
#tensor([[2, 2, 2, 2, 2, 2],
# [2, 2, 2, 2, 2, 2]])
RuntimeError: unsupported operation: more than one element of the written-to tensor refers to a single memory location. Please clone() the tensor before performing the operation.
出现这种情况可能是在.backward()之前使用了 .expand()或者.expand_as()函数。在 .expand()或者.expand_as()函数后面添加.clone()就可以解决。
torch.repeat_interleave(input, repeats, dim=None) → Tensor
dim是需要重复的维度
y = torch.tensor([[1, 2], [3, 4]])
torch.repeat_interleave(y,3,0)
tensor([[1, 2],
[1, 2],
[1, 2],
[3, 4],
[3, 4],
[3, 4]])
tensor.tolist()
test_data = datasets.ImageFolder(root=os.path.join(DIR['ImageNet'], 'val'), transform=trans)