【问题标题】:How can I sort 128 bit unsigned integers in Python?如何在 Python 中对 128 位无符号整数进行排序?
【发布时间】:2019-03-26 00:28:36
【问题描述】:

我有大量 128 位无符号整数需要排序以供分析(大约一万亿!)。

我对 128 位整数所做的研究让我走入了一条死胡同,numpy 似乎并不完全支持它们,而且内部排序功能是内存密集型的(使用列表)。

例如,我想要将十亿个 128 位无符号整数加载到内存中(如果只是二进制数据,则为 16GB)并对它们进行排序。有问题的机器有 48GB 的​​ RAM,所以应该可以使用 32GB 进行操作。如果必须在较小的块中完成,那没关系,但是尽可能大的块会更好。 Python 是否有一种排序算法可以在不需要大量开销的情况下获取此类数据?

我可以使用列表的 .sort 方法对 128 位整数进行排序,它可以工作,但它无法扩展到我需要的级别。我确实有一个 C++ 版本,它是定制编写的,并且运行速度非常快,但我想在 Python 中复制它以加快开发时间(而且我没有编写 C++,而且我不习惯那种语言) .

抱歉,如果需要更多信息来描述问题,请提出任何问题。

【问题讨论】:

  • 你能把数字写入一个文本文件,每行一个,然后在命令行中使用sort -n吗?
  • John,谢谢,但我认为文本文件不会有帮助,因为当数据以二进制文件表示时已经是 16TB。这可能适用于某些类型的排序,特别是如果它是一次性的,但我猜测(但可能是错误的)它也不会很好地扩展。

标签: python sorting numpy int128


【解决方案1】:

NumPy 不支持 128 位整数,但如果您使用由高位和低位无符号 64 位块组成的结构化 dtype,它们将按照与 128 位整数相同的顺序进行排序:

arr.sort(order=['high', 'low'])

至于您将如何获得具有该 dtype 的数组,这取决于您首先如何加载数据。我想它可能涉及调用ndarray.view 来重新解释另一个数组的字节。例如,如果您有一个 dtype uint8 数组,其字节应被解释为 little-endian 128 位无符号整数,则在 little-endian 机器上:

arr_structured = arr_uint8.view([('low', 'uint64'), ('high', 'uint64')])

所以这对于十亿个整数来说可能是合理的,但你说你已经得到了大约一个 万亿 个。这比 48GB RAM 计算机上的内存排序要多得多。您还没有要求一次处理整个万亿元素数据集,所以我希望您已经想到了一个好的解决方案来合并排序的块,或者对数据集进行预分区。

【讨论】:

  • 谢谢,我会调查并报告。我有一个解决数千/秒排序块的解决方案。它们不需要合并,因为它们根据前 10 位预先分类为 1048 个文件。考虑到这一点,创建了 1048 个源文件(每个大约十亿个 128 位整数)。最重要的任务是进行分析,但这是另一回事,这就是为什么像 Python 这样的快速开发环境(在较小规模上对其进行测试)是完美的。
  • 我的结果,虽然我是新手,但表明 NumPy 比这个用例的内置列表排序慢。具有随机数据的 NumPy 数组的填充速度是类似于列表的两倍(首先创建一个归零的 NumPy 数组,然后循环将随机 uint64 值放入数组中,列表能够被赋予一个随机 uint128,之后也被创建归零,这可能解释了差异)。分拣速度稍微慢了一点,大概在 30% 左右。谢谢你的建议,不管怎样,它教会了我一些东西。进一步拆分源文件似乎是最简单的方法
  • @LocalGeek:手动循环遍历 NumPy 数组很慢。你不应该在 Python 级别遍历它们;您应该以将循环推送到 C 中的方式编写代码,例如将 size 参数传递给 numpy.random.randint
  • 谢谢。我有点知道我没有正确地做那部分 - 我只是想模拟一个缓慢的填充方法,因为我不知道从磁盘加载 ndarray 将如何执行。重要的一点是排序,结果证明它的速度与内置列表相似 - 可能是因为列表能够在本机 C 中使用 128 位 int 而 NumPy(其他方面非常出色)还没有做到这一点.虽然我可能没有最佳答案,但我找到了一些对我有用的东西 - 你的建议很有帮助。
  • @LocalGeek:没有原生的 128 位整数。 Python 正在使用任意精度的整数实现。我认为时间差异可能是由于次优的结构化 dtype 处理,可能与无法优化比较有关。
【解决方案2】:

我可能对 Python 期望过高,但我并不失望。几分钟的编码让我创建了一些东西(使用内置列表),可以在几分钟内处理对 8GB 笔记本电脑上的一亿个 uint128 项目的排序。

考虑到要排序的大量项目(1 万亿),很明显,在创建时将它们放入较小的 bin/文件中比在内存中对大量数字进行排序更有意义。通过将数据附加到 1MB 块中的数千个文件(旋转磁盘上的碎片)所产生的潜在问题并不那么令人担忧,因为这些碎片文件中的每一个都会创建一个将被多次读取的顺序文件(碎片文件是一次写一次读一次)。

与 C/C++ 相比,Python 开发速度的优势似乎超过了性能损失,尤其是因为排序只发生一次。

【讨论】:

    猜你喜欢
    • 2016-10-11
    • 1970-01-01
    • 2020-07-06
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    • 2010-10-21
    • 2011-07-29
    相关资源
    最近更新 更多