python - Pytables 复制 2.5 giga 行
问题描述
我目前有一个 .h5 文件,其中的表格由三列组成:一个 64 个字符的文本列,一个与文本源相关的 UInt32 列和一个 UInt32 列,它是文本的 xxhash。该表由 ~ 2.5e9 行组成
我正在尝试查找并计算表中每个文本条目的重复项 - 基本上将它们合并到一个条目中,同时计算实例。我已经尝试通过在哈希列上建立索引然后循环执行此操作table.itersorted(hash)
,同时跟踪哈希值并检查冲突 - 非常类似于在具有 500e6 行的 hdf5 pytable 中查找重复项。我没有在循环时修改表格,而是将合并的条目写入新表格 - 我将代码放在底部。
基本上我遇到的问题是整个过程花费的时间太长了——我花了大约 20 个小时才到达迭代 #5 4e5。但是,我正在使用硬盘驱动器,因此完全有可能存在瓶颈。你有什么方法可以改进我的代码,或者你能建议另一种方法吗?预先感谢您的任何帮助。
PS我保证我没有做任何违法的事情,这只是我的学士论文的大规模泄露密码分析。
ref = 3 #manually checked first occuring hash, to simplify the below code
gen_cnt = 0
locs = {}
print("STARTING")
for row in table.itersorted('xhashx'):
gen_cnt += 1 #so as not to flush after every iteration
ps = row['password'].decode(encoding = 'utf-8', errors = 'ignore')
if row['xhashx'] == ref:
if ps in locs:
locs[ps][0] += 1
locs[ps][1] |= row['src']
else:
locs[ps] = [1, row['src']]
else:
for p in locs:
fill_password(new_password, locs[ps]) #simply fills in the columns, with some fairly cheap statistics procedures
new_password.append()
if (gen_cnt > 100):
gen_cnt = 0
new_table.flush()
ref = row['xhashx']```
解决方案
您的数据集比引用的解决方案大 10 倍(2.5e9 与 500e6 行)。你有没有做过任何测试来确定时间花在哪里?该table.itersorted()
方法可能不是线性的 - 并且可能是资源密集型的。(我没有任何迭代的经验。)
这是一个可能更快的过程:
- 提取哈希字段的 NumPy 数组(列
xhashx
) - 找到唯一的哈希值
- 遍历唯一的哈希值并提取与每个值匹配的 NumPy 行数组
- 对此提取的数组中的行进行唯一性测试
- 将唯一行写入新文件
下面这个过程的代码:
注意:这没有经过测试,所以可能有小的语法或逻辑差距
# Step 1: Get a Numpy array of the 'xhashx' field/colmu only:
hash_arr = table.read(field='xhashx')
# Step 2: Get new array with unique values only:
hash_arr_u = np.unique(hash_arr)
# Alternately, combine first 2 steps in a single step
hash_arr_u = np.unique(table.read(field='xhashx'))
# Step 3a: Loop on rows unique hash values
for hash_test in hash_arr_u :
# Step 3b: Get an array with all rows that match this unique hash value
match_row_arr = table.read_where('xhashx==hash_test')
# Step 4: Check for rows with unique values
# Check the hash row count.
# If there is only 1 row, uniqueness tested not required
if match_row_arr.shape[0] == 1 :
# only one row, so write it to new.table
else :
# check for unique rows
# then write unique rows to new.table
##################################################
# np.unique has an option to save the hash counts
# these can be used as a test in the loop
(hash_arr_u, hash_cnts) = np.unique(table.read(field='xhashx'), return_counts=True)
# Loop on rows in the array of unique hash values
for cnt in range(hash_arr_u.shape[0]) :
# Get an array with all rows that match this unique hash value
match_row_arr = table.read_where('xhashx==hash_arr_u(cnt)')
# Check the hash row count.
# If there is only 1 row, uniqueness tested not required
if hash_cnts[cnt] == 1 :
# only one row, so write it to new.table
else :
# check for unique rows
# then write unique rows to new.table
推荐阅读
- java - Vaadin 14 在重新打包后无法导航到“”
- python - 在 python 3.7 上安装 TA-Lib
- sql - Sql从具有相同外部ID和日期记录的表中获取不同的记录,该记录在它自己的记录和3分钟之后
- java - 如何修复“hdfs://192.123.81.123:9000/atos/sample.pdf 不是序列文件”
- python-3.x - 这种类型的图像显示是如何用 scikit-learn 完成的?
- json - 无法在颤动中使用对象预填充下拉列表
- javascript - 是否可以为每个滚动的像素触发 onScroll 事件?
- java - 我在 if 和 else 语句中给出的费率没有按应有的方式加起来
- javascript - JS 等待一个递归函数来查找 Android 上的所有 MP3 文件
- android - 从命令行构建 APK 与 Android Studio 的 [绿色] 播放按钮的行为不同