xMillion 条目的匿名化 - 需要性能提示
Posted
技术标签:
【中文标题】xMillion 条目的匿名化 - 需要性能提示【英文标题】:Anonymisation of xMillion entries - need performance hints 【发布时间】:2021-09-07 15:35:57 【问题描述】:编辑:在每次调用时初始化名称数据集是一个巨大的错误(它将黑名单名称数据集加载到内存中)。 刚刚将 m = NameDataset() 移至主函数。没有测量,但它现在至少快 100 倍。
我使用dataTables 开发了一个(多语言)且可快速搜索的数据库。我想匿名化 mysql 数据库中的一些数据(名称等)。 在第一个例子中,我使用了 spaCy - 但因此字典没有经过训练 - 结果有太多误报。现在我对name-dataset 很满意。当然,它的工作方式完全不同,而且速度比 spaCy 慢得多,这得益于 GPU-Power。
因此自定义名称-DB 变得非常大(350.000 行)并且目标 DB 非常大 - 在循环中使用 regex.finditer 处理每个找到的单词需要永远(Ryzen 7 3700X) . 我们可以说 5 例/秒 - 这使得数百万行超过 100 小时。 因此每个进程只消耗大约 10% 的 CPU 功率,我启动了几个(最多 10 个)python 进程 - 最后它仍然需要很长时间。
我希望,我再也不必这样做了——但我害怕,我必须这样做。 所以我问,你有以下例程的性能提示吗?
main() 中的外部 for 循环 - 循环通过管道对象(DB 行)并调用 3 次(= 3 个项目/列)anonymize() 它也有一个 for 循环,贯穿每个找到的单词重写它们,使用 CUDA/numba(可用 RTX 2070)等有意义吗? 还有其他性能提示吗?谢谢!
import simplejson as json
import sys, regex, logging, os
from names_dataset import NameDataset
def anonymize(sourceString, col):
replacement = 'xxx'
output = ''
words = sourceString.split(' ')
#and this second loop for each word (will run three times per row)
for word in words:
newword = word
#regex for findind/splitting the words
fRegExStr = r'(?=[^\s\r\n|\(|\)])(\w+)(?=[\.\?:,!\-/\s\(\)]|$)'
pattern = regex.compile(fRegExStr)
regx = pattern.finditer(word)
if regx is None:
if m.search_first_name(word, use_upper_Row=True):
output += replacement
elif m.search_last_name(word, use_upper_Row=True):
output += replacement
else:
output += word
else:
for eachword in regx:
if m.search_first_name(eachword.group(), use_upper_Row=True):
newword = newword.replace(eachword.group(), replacement)
elif m.search_last_name(eachword.group(), use_upper_Row=True):
newword = newword.replace(eachword.group(), replacement)
output += newword
output += ' '
return output
def main():
#object with data is been piped to the python script, data structure:
#MyRows:
# [Text_A: 'some text', Text_B: 'some more text', Text_C: 'still text'],
# [Text_A: 'some text', Text_B: 'some more text', Text_C: 'still text'],
# ....several thousand rows
#
MyRows = json.load(sys.stdin, 'utf-8')
#this is the first outer loop for each row
for Row in MyRows:
xText_A = Row['Text_A']
if Row['Text_A'] and len(Row['Text_A']) > 30:
Row['Text_A'] = anonymize(xText_A, 'Text_A')
xText_B = Row['Text_B']
if xText_B and len(xText_B) > 10:
Row['Text_B'] = anonymize(xText_B, 'Text_B')
xMyRowText_C = Row['MyRowText_C']
if xMyRowText_C and len(xMyRowText_C) > 10:
Row['MyRowText_C'] = anonymize(xMyRowText_C, 'MyRowText_C')
retVal = json.dumps(MyRows, 'utf-8')
return retVal
if __name__ == '__main__':
m = NameDataset() ## Right here is good - THIS WAS THE BOTTLENECK ##
retVal = main()
sys.stdout.write(str(retVal))
【问题讨论】:
如果不涉及数据库,请去掉标签[mysql]
【参考方案1】:
你在做
for word in words:
newword = word
#regex for findind/splitting the words
fRegExStr = r'(?=[^\s\r\n|\(|\)])(\w+)(?=[\.\?:,!\-/\s\(\)]|$)'
pattern = regex.compile(fRegExStr)
regx = pattern.finditer(word)
意思是你regex.compile
完全相同的事情在每个循环中,而你可以在循环开始之前做它并获得相同的结果。
我没有看到其他明显的优化,所以我建议profile 代码找出最耗时的部分。
【讨论】:
谢谢@Daweo。瓶颈在每次调用时都会初始化“m = NameDataset()”。将其移至 main() - 现在可以接受的速度很快。也感谢个人资料的提示!以上是关于xMillion 条目的匿名化 - 需要性能提示的主要内容,如果未能解决你的问题,请参考以下文章