如何在Python中实现真正高效的位向量排序

发布于 2024-09-05 04:27:17 字数 2040 浏览 4 评论 0原文

实际上,这是珍珠编程中的一个有趣的主题,使用有效的算法在有限的内存中对 10 位电话号码进行排序。您可以在此处找到整个故事,

我感兴趣的是速度有多快可以用 python 实现。我已经使用模块位向量完成了一个简单的实现。代码如下:

from BitVector import BitVector
import timeit
import random
import time
import sys

def sort(input_li):
        return sorted(input_li)

def vec_sort(input_li):
        bv = BitVector( size = len(input_li) )
        for i in input_li:
                bv[i] = 1

        res_li = []
        for i in range(len(bv)):
                if bv[i]:
                        res_li.append(i)

        return res_li

if __name__ == "__main__":
        test_data = range(int(sys.argv[1]))
        print 'test_data size is:', sys.argv[1]
        random.shuffle(test_data)

        start = time.time()
        sort(test_data)
        elapsed = (time.time() - start)
        print "sort function takes " + str(elapsed)
        start = time.time()
        vec_sort(test_data)
        elapsed = (time.time() - start)
        print "sort function takes " + str(elapsed)
        start = time.time()
        vec_sort(test_data)
        elapsed = (time.time() - start)
        print "vec_sort function takes " + str(elapsed)

我在我的macbook(2GHz Intel Core 2 Duo 2GB SDRAM)中从数组大小100到10,000,000进行了测试,结果如下:


  • test_data size is: 1000
  • sort function 需要 0.000274896621704
  • vec_sort 函数需要 0.00383687019348

  • test_data 大小为:10000

  • 排序函数需要 0.00380706787109
  • < p>vec_sort 函数需要 0.0371489524841

  • test_data 大小为:100000

  • 排序函数需要 0.05205​​60741425
  • vec_sort 函数需要 0.374383926392

  • test_数据大小为:1000000

  • 排序函数需要 0.867373943329
  • vec_sort 函数需要 3.80475401878

  • test_data 大小为:10000000

  • 排序函数需要 12。 9204008579
  • vec_sort函数需要38.8053860664

令我失望的是,即使当 test_data 大小为 100,000,000 时,排序函数仍然比 vec_sort 更快。有什么方法可以加速 vec_sort 函数吗?

Actually this is an interesting topic from programming pearls, sorting 10 digits telephone numbers in a limited memory with an efficient algorithm. You can find the whole story here

What I am interested in is just how fast the implementation could be in python. I have done a naive implementation with the module bitvector. The code is as following:

from BitVector import BitVector
import timeit
import random
import time
import sys

def sort(input_li):
        return sorted(input_li)

def vec_sort(input_li):
        bv = BitVector( size = len(input_li) )
        for i in input_li:
                bv[i] = 1

        res_li = []
        for i in range(len(bv)):
                if bv[i]:
                        res_li.append(i)

        return res_li

if __name__ == "__main__":
        test_data = range(int(sys.argv[1]))
        print 'test_data size is:', sys.argv[1]
        random.shuffle(test_data)

        start = time.time()
        sort(test_data)
        elapsed = (time.time() - start)
        print "sort function takes " + str(elapsed)
        start = time.time()
        vec_sort(test_data)
        elapsed = (time.time() - start)
        print "sort function takes " + str(elapsed)
        start = time.time()
        vec_sort(test_data)
        elapsed = (time.time() - start)
        print "vec_sort function takes " + str(elapsed)

I have tested from array size 100 to 10,000,000 in my macbook(2GHz Intel Core 2 Duo 2GB SDRAM), the result is as following:


  • test_data size is: 1000
  • sort function
    takes 0.000274896621704
  • vec_sort function takes 0.00383687019348

  • test_data size is: 10000

  • sort function takes 0.00380706787109
  • vec_sort function takes 0.0371489524841

  • test_data size is: 100000

  • sort function takes 0.0520560741425
  • vec_sort function takes 0.374383926392

  • test_data size is: 1000000

  • sort function takes 0.867373943329
  • vec_sort function takes 3.80475401878

  • test_data size is: 10000000

  • sort function takes 12.9204008579
  • vec_sort function takes 38.8053860664

What disappoints me is that even when the test_data size is 100,000,000, the sort function is still faster than vec_sort. Is there any way to accelerate the vec_sort function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

任性一次 2024-09-12 04:27:17

正如 Niki 指出的,您正在将非常快速的 C 例程与 Python 例程进行比较。使用 psyco 对我来说会加快一点速度,但是你可以通过使用位向量来加快速度用C编写的模块。我使用了 bitarray 然后位排序方法超越了使用 psyco 对大约 250,000 的数组大小进行内置排序。

这是我使用的函数:

def vec_sort2(input_li):
    bv = bitarray(len(input_li))
    bv.setall(0)
    for i in input_li:
        bv[i] = 1

    return [i for i in xrange(len(bv)) if bv[i]]

另请注意,我使用了列表理解来构造排序列表,这有点帮助。将 psyco 和上述函数与您的函数一起使用,我得到以下结果:

test_data size is: 1000000
sort function takes 1.29699993134
vec_sort function takes 3.5150001049
vec_sort2 function takes 0.953999996185

作为旁注,BitVector 即使对于 Python 也没有特别优化。在找到 bitarray 之前,我对模块做了一些不同的调整,并使用经过调整的模块,对于这种大小的数组,vec_sort 的时间减少了一秒多。不过,我还没有提交对它的更改,因为位数组要快得多。

As Niki pointed out, you are comparing a very fast C routine with a Python one. Using psyco speeds it up a little bit for me, but you can really speed it up by using a bit vector module written in C. I used bitarray and then the bit sorting method surpasses the built-in sort for an array size of about 250,000 using psyco.

Here's the function that I used:

def vec_sort2(input_li):
    bv = bitarray(len(input_li))
    bv.setall(0)
    for i in input_li:
        bv[i] = 1

    return [i for i in xrange(len(bv)) if bv[i]]

Notice also that I have used a list comprehension to construct the sorted list which helps a bit. Using psyco and the above function with your functions I get the following results:

test_data size is: 1000000
sort function takes 1.29699993134
vec_sort function takes 3.5150001049
vec_sort2 function takes 0.953999996185

As a side note, BitVector isn't especially optimized even for Python. Before I found bitarray, I did some various tweaks to the module and using my module that has the tweaks, the time for vec_sort is reduced over a second for this size of an array. I haven't submitted my changes to it though because bitarray is just so much faster.

怪我太投入 2024-09-12 04:27:17

我的Python不是最好的,但看起来你的代码中有一个错误:

bv = BitVector( size = len(input_li) )

位向量的大小与输入数组的大小相同。您希望位向量是域的大小 - 10^10。我不确定Python的位向量如何处理溢出,但如果它自动调整位向量的大小,那么你就会得到二次行为。

另外,我认为 Python 的排序函数是用 C 实现的,并且不会有纯粹用 Python 实现的排序的开销。然而,这可能不会导致 O(nlogn) 算法的运行速度明显快于 O(n) 算法。

编辑:这种排序也仅适用于大型数据集。您的算法在 O(n + 10^10) 时间内运行(根据您的测试,我假设您知道这一点),对于小输入,这将比 O(nlogn) 更糟糕。

My Python isn't the best but it looks like you have a bug in your code:

bv = BitVector( size = len(input_li) )

The size of your bitvector is the same as the size of your input array. You want the bitvector to be the size of your domain - 10^10. I'm not sure how Python's bitvectors deal with overflows, but if it automatically resizes the bitvector then you are getting quadratic behavior.

Additionally I imagine that Python's sort function is implemented in C and is not going to have the overhead of a sort implemented purely in Python. However that probably wouldn't cause an O(nlogn) algorithm to run substantially faster than an O(n) algorithm.

Edit: also this sort will only work on large data sets. Your algorithm runs in O(n + 10^10) time (based on your tests I assume you know this) which will be worse than O(nlogn) for small inputs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文