我正在实现滚动中值解决方案,并且不确定为什么我的python实现比c ++实现慢大约40倍。
以下是完整的实施
C ++
#include <iostream>
#include <vector>
#include <string.h>
using namespace std;
int tree[17][65536];
void insert(int x) { for (int i=0; i<17; i++) { tree[i][x]++; x/=2; } }
void erase(int x) { for (int i=0; i<17; i++) { tree[i][x]--; x/=2; } }
int kThElement(int k) {
int a=0, b=16;
while (b--) { a*=2; if (tree[b][a]<k) k-=tree[b][a++]; }
return a;
}
long long sumOfMedians(int seed, int mul, int add, int N, int K) {
long long result = 0;
memset(tree, 0, sizeof(tree));
vector<long long> temperatures;
temperatures.push_back( seed );
for (int i=1; i<N; i++)
temperatures.push_back( ( temperatures.back()*mul+add ) % 65536 );
for (int i=0; i<N; i++) {
insert(temperatures[i]);
if (i>=K) erase(temperatures[i-K]);
if (i>=K-1) result += kThElement( (K+1)/2 );
}
return result;
}
// default input
// 47 5621 1 125000 1700
// output
// 4040137193
int main()
{
int seed,mul,add,N,K;
cin >> seed >> mul >> add >> N >> K;
cout << sumOfMedians(seed,mul,add,N,K) << endl;
return 0;
}
的Python
def insert(tree,levels,n):
for i in xrange(levels):
tree[i][n] += 1
n /= 2
def delete(tree,levels,n):
for i in xrange(levels):
tree[i][n] -= 1
n /= 2
def kthElem(tree,levels,k):
a = 0
for b in reversed(xrange(levels)):
a *= 2
if tree[b][a] < k:
k -= tree[b][a]
a += 1
return a
def main():
seed,mul,add,N,K = map(int,raw_input().split())
levels = 17
tree = [[0] * 65536 for _ in xrange(levels)]
temps = [0] * N
temps[0] = seed
for i in xrange(1,N):
temps[i] = (temps[i-1]*mul + add) % 65536
result = 0
for i in xrange(N):
insert(tree,levels,temps[i])
if (i >= K):
delete(tree,levels,temps[i-K])
if (i >= K-1):
result += kthElem(tree,levels,((K+1)/2))
print result
# default input
# 47 5621 1 125000 1700
# output
# 4040137193
main()
在上面提到的输入中(在代码的注释中)C ++代码花了0.06 seconds
而python花了2.3 seconds
。
有人可以提出我的python代码可能出现的问题,以及如何将性能提高到不到10倍?
我不希望它接近c ++实现,但是大约5-10x。我知道我可以通过使用像numpy(和/或scipy)这样的库来优化它。我从使用python解决编程挑战的角度来问这个问题。这些挑战中通常不允许使用这些库。我只想问是否有可能在python中击败这个算法的时间限制。
如果有人感兴趣,C ++代码是从http://community.topcoder.com/tc?module=Static&d1=match_editorials&d2=srm310
的浮动中位数问题借来的对于那些认为使用numpy数组会改善性能的人来说,它并没有。另一方面,只使用numpy ndarray而不是列表列表,性能进一步降低到大约14秒,这比c ++慢了200倍。
答案 0 :(得分:4)
如果您想尝试使用纯Python来提高性能,可以尝试使用“cProfile”模块来分析代码。但它可能无法接近C ++速度,除非您使用NumPy等更智能的模块或编写自己的扩展。
通过重构,您可能会获得少量收益:
reversed(xrange(levels))
特别是如果您使用的是Python 2.x,因为这将创建一个实际的列表。你可以这样做:
xrange(levels - 1, -1, -1)
答案 1 :(得分:2)
有人可以建议如何将性能提高到不到10倍?