これは、Pythonが実際にどれくらい遅いかというフォローアップです (または、どのくらいの速あなたの言語で?) 。
最後の質問で100倍のスピードアップを得るのは少し簡単すぎることがわかりました。チャレンジを楽しんでいるが、低レベルのスキルを実際に使用できるより難しいものが必要な場合は、パートIIをご覧ください。課題は、私のコンピューターでテストされた次のpythonコードのx100の高速化を得ることです。
さらに難しくするために、今回はpypyを使用しています。私の現在のタイミングは、pypy 2.2.1を使用して1分7秒です。
ルール
- 私が実行できるコードを送信した最初の人は正しいですし、私のマシンで100倍高速である場合、50ポイントの報奨金が授与されます。
- 私は一週間後に最速のコードに勝利を授与します。
import itertools
import operator
import random
n = 8
m = 8
iters = 1000
# creates an array of 0s with length m
# [0, 0, 0, 0, 0, 0, 0, 0]
leadingzerocounts = [0]*m
# itertools.product creates an array of all possible combinations of the
# args passed to it.
#
# Ex:
# itertools.product("ABCD", "xy") --> Ax Ay Bx By Cx Cy Dx Dy
# itertools.product("AB", repeat=5) --> [
# ('A', 'A', 'A', 'A', 'A'),
# ('A', 'A', 'A', 'A', 'B'),
# ('A', 'A', 'A', 'B', 'A'),
# ('A', 'A', 'A', 'B', 'B'),
# etc.
# ]
for S in itertools.product([-1,1], repeat = n+m-1):
for i in xrange(iters):
F = [random.choice([-1,0,0,1]) for j in xrange(n)]
# if the array is made up of only zeros keep recreating it until
# there is at least one nonzero value.
while not any(F):
F = [random.choice([-1,0,0,1]) for j in xrange(n)]
j = 0
while (j < m and sum(map(operator.mul, F, S[j:j+n])) == 0):
leadingzerocounts[j] +=1
j += 1
print leadingzerocounts
出力は次のようになります
[6335185, 2526840, 1041967, 439735, 193391, 87083, 40635, 19694]
コード内でランダムシードを使用する必要があり、上記に近い回答を提供するのに十分な乱数ジェネレーターが受け入れられます。
私のマシンタイミングは私のマシンで実行されます。これは、AMD FX-8350 8コアプロセッサへの標準のUbuntuインストールです。これは、コードを実行できる必要があることも意味します。
コードの説明
このコードは、-1と1で構成される長さn + m-1のすべての配列Sを反復処理します。各配列Sに対して、長さnが-1、0または1で構成される1000個の非ゼロランダム配列Fをサンプリングし、各値を取得する確率を1 / 4、1 / 2、/ 14にします。次に、Fと、長さnのSの各ウィンドウとの間の内積を計算し、非ゼロの内積を見つけます。leadingzerocounts
ゼロの内積が見つかった各位置に1を加算します。
状態
Perlの。@tobyinkによる2.7倍のスローダウン。(cpythonではなくpypyと比較。)
J。@Eelvexによる39倍の高速化。
- C。@aceで59倍高速化します。
- ジュリア。@ one-more-分による起動時間を含まずに197倍高速。起動時間を含めて8.5倍に高速化されます(この場合、8個よりも4個のプロセッサを使用した方が高速です)。
- Fortranの。@ semi-extrinsicにより438倍に高速化されます。
- Rpython。@primoによって258倍の速度になります。
- C ++。@ilmaleにより508倍の速度になります。
(新しい改善が速すぎてitersが小さすぎたため、新しい改善のタイミングを止めました。)
1秒未満のタイミングは信頼性が低く、一部の言語には起動コストがかかることが指摘されました。引数は、含める場合はC / C ++などのコンパイル時間も含める必要があるということです。ここに、反復回数が100,000に増加した最速のコードのタイミングを示します。
- ジュリア。@ one-more-minuteで42秒。
- C ++。@GuySirtonによる14秒。
- Fortranの。@ semi-extrinsicによる14秒。
- C ++。@ilmaleによる12秒。
- Rpython。@primoによる18秒。
- C ++。@Stefanによる5秒。
勝者は..ステファンです!
フォローアップの課題が投稿されました。あなたはどれくらい高く行くことができますか?(コーディング+アルゴリズムの挑戦)。これは難しいです。