Python 3.x Python代码在包装到函数中时会变慢

Python 3.x Python代码在包装到函数中时会变慢,python-3.x,dataset,pytorch,Python 3.x,Dataset,Pytorch,我正在读取和处理一个文件(使用相同的代码位),该文件以两种截然不同的速度运行:1。脚本化(每秒50K+迭代次数)和2。包装在函数中(每秒约300次迭代)。我真的不明白为什么在阅读时间消耗上有如此巨大的差异 模块结构(省略了未使用和不相关的文件。代码在末尾): 在data.py中,我们有方法(load,包装方法的类继承自torch.utils.data.Dataset)实际加载文件。在dataloaders.py中,我准备了要传递给load的参数,并为我使用的每个数据集包装在一个函数中。然后将其传

我正在读取和处理一个文件(使用相同的代码位),该文件以两种截然不同的速度运行:1。脚本化(每秒50K+迭代次数)和2。包装在函数中(每秒约300次迭代)。我真的不明白为什么在阅读时间消耗上有如此巨大的差异

模块结构(省略了未使用和不相关的文件。代码在末尾):

data.py
中,我们有方法(
load
,包装方法的类继承自
torch.utils.data.Dataset
)实际加载文件。在
dataloaders.py
中,我准备了要传递给
load
的参数,并为我使用的每个数据集包装在一个函数中。然后将其传递给
加载程序
函数,该函数处理数据集的拆分等操作

实验中,跑步者
就是速度差异发生的地方。如果我使用
dataloaders.py
中的dataset函数,加载速度大约为300次迭代/秒。如果我从函数中复制代码并将其直接放入
实验运行程序
,仍然使用
dataloaders.py
中的
loader
函数(因此,没有为每个数据集包装一个函数),加载大约以50000次/秒的速度进行。我完全不明白为什么在函数中包装代码会极大地改变它的速度

现在实际代码是:

data.py:

def加载(self,数据集:str='train',skip_header=True,**kwargs)->无:
fp=打开(self.data\u文件[数据集])
如果跳过标题:
下一步(fp)
数据=[]
对于tqdm中的行(self.reader(fp),desc=f'loading{self.name}({dataset})):
data_行,datapoint={},base.datapoint()
对于self.train_字段中的字段:
idx=field.index,如果self.ftype在['CSV','TSV']else field.cname中
数据\行[field.name]=self.process\文档(行[idx].rstrip())
数据行['original']=行[idx].rstrip()
对于self.label_字段中的字段:
idx=field.index,如果self.ftype在['CSV','TSV']else field.cname中
如果self.label\u预处理器:
数据行[field.name]=self.label\u预处理器(行[idx].rstrip())
其他:
数据行[field.name]=行[idx].rstrip()
对于键,数据行中的val.items():
setattr(数据点、键、值)
data.append(数据点)
fp.close()
如果self.length为“无”:
#获取最大长度
镜头=[]
对于数据中的文档:
对于self.train_字段中的f:
lens.append(len([tok代表getattr中的tok(doc,getattr(f,'name'))]))
self.length=最大值(镜头)
如果数据集==‘训练’:
self.data=数据
elif数据集=='dev':
self.dev=数据
elif数据集==“测试”:
自检=数据
dataloaders.py:

def加载器(args:dict,**kwargs):
“”“加载数据集。
:args(dict):包含用于加载数据集的参数的dict。
:返回:加载和拆分的数据集。
"""
dataset=GeneralDataset(**args)
数据集.装载('列车',**kwargs)
如果(args['dev'],args['test'])==(无,无):#只给出列车组。
dataset.split(dataset.data,[0.8,0.1,0.1],**kwargs)
elif args['dev']不是None,args['test']是None:#给定了dev集,请不要测试它。
dataset.load('dev',**kwargs)
dataset.split(dataset.data,[0.8],**kwargs)
elif args['dev']为无,args['test']为非无:#test已给出,dev未给出。
dataset.split(dataset.data,[0.8],**kwargs)
dataset.dev_set=dataset.test
dataset.load('test',**kwargs)
else:#给出了开发集和测试集。
dataset.load('dev',**kwargs)
dataset.load('test',**kwargs)
返回数据集
def二进制化(标签:str)->str:
如果标签位于['0','1']:
返回“pos”
其他:
返回“负”
def datal(路径:str,清除器:base.Callable,预处理器:base.Callable=None):
args={'data_dir':路径,
“ftype”:“csv”,
“字段”:无,
'train':'dataset.csv','dev':无,'test':无,
“训练标签”:无,“开发标签”:无,“测试标签”:无,
"九月":",,
“标记器”:lambda x:x.split(),
“预处理器”:预处理器,
“转换”:无,
“长度”:无,
“label_预处理器”:二值化,
“名称”:“第一个数据集。”
}
忽略=基本字段('ignore',train=False,label=False,ignore=True)
d_text=base.Field('text',train=True,label=False,ignore=False,ix=6,cname=text'))
d_label=base.Field('label',train=False,label=True,cname='label',ignore=False,ix=5)
args['fields']=[忽略,忽略,忽略,忽略,忽略,d_标签,d_文本]
返回加载器(args)
并为此目的: 实验_runner.py

from module.dataloaders import datal, loader

dataset = datal() # Slow: 300-ish iterations/second

# Fast version: 50000 iter/second
def binarize(label: str) -> str:
    if label in ['0', '1']:
        return 'pos'
    else:
        return 'neg'

args = {'data_dir': path,
        'ftype': 'csv',
        'fields': None,
        'train': 'dataset.csv', 'dev': None, 'test': None,
        'train_labels': None, 'dev_labels': None, 'test_labels': None,
        'sep': ',',
        'tokenizer': lambda x: x.split(),
        'preprocessor': preprocessor,
        'transformations': None,
        'length': None,
        'label_preprocessor': binarize,
        'name': 'First dataset.'
        }

ignore = base.Field('ignore', train = False, label = False, ignore = True)
d_text = base.Field('text', train = True, label = False, ignore = False, ix = 6, cname = 'text')
d_label = base.Field('label', train = False, label = True, cname = 'label', ignore = False, ix = 5)

args['fields'] = [ignore, ignore, ignore, ignore, ignore, d_label, d_text]

dataset = loader(args)

理想情况下,我更愿意将数据集函数(例如,
datal
)包装起来,以保持逻辑独立,但随着速度的降低,这是不可行的。

你能删除所有
\uuupycache\uuu
文件夹并重新检查吗?@cozek好的,这改变了一些事情。现在两个循环以相同的速度运行(慢速版本)。但是为什么会链接到
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。现在两个循环以相同的速度运行(慢速版本)。但为什么会链接到
\uuuuu pycache\uuuuu
文件夹?
from module.dataloaders import datal, loader

dataset = datal() # Slow: 300-ish iterations/second

# Fast version: 50000 iter/second
def binarize(label: str) -> str:
    if label in ['0', '1']:
        return 'pos'
    else:
        return 'neg'

args = {'data_dir': path,
        'ftype': 'csv',
        'fields': None,
        'train': 'dataset.csv', 'dev': None, 'test': None,
        'train_labels': None, 'dev_labels': None, 'test_labels': None,
        'sep': ',',
        'tokenizer': lambda x: x.split(),
        'preprocessor': preprocessor,
        'transformations': None,
        'length': None,
        'label_preprocessor': binarize,
        'name': 'First dataset.'
        }

ignore = base.Field('ignore', train = False, label = False, ignore = True)
d_text = base.Field('text', train = True, label = False, ignore = False, ix = 6, cname = 'text')
d_label = base.Field('label', train = False, label = True, cname = 'label', ignore = False, ix = 5)

args['fields'] = [ignore, ignore, ignore, ignore, ignore, d_label, d_text]

dataset = loader(args)