Це подання на те, наскільки повільно Python насправді? (Або наскільки швидкою є ваша мова?) .
Виявляється, для мого останнього запитання було надто просто отримати швидкість x100. Для тих, хто сподобався виклику, але хоче щось важче, де реально використовувати свої навички низького рівня, ось частина II. Завдання полягає в тому, щоб отримати прискорення x100 для наступного коду python, перевіреного на моєму комп’ютері.
Щоб зробити це складніше, я зараз використовую pypy. Поточний час для мене становить 1 хвилину та 7 секунд за допомогою pypy 2.2.1.
Правила
- Перший, хто подав код, який я можу запустити, є правильним і на 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]
Ви повинні використовувати випадковий насіння у своєму коді, і будь-який генератор випадкових чисел, який достатньо хороший, щоб дати відповіді, близькі до вище, буде прийнято.
My Machine Часи синхронізуються на моїй машині. Це стандартна установка ubuntu на восьмиядерний процесор AMD FX-8350. Це також означає, що мені потрібно мати можливість запускати ваш код.
Пояснення коду
Цей код повторює всі масиви S довжиною n + m-1, складені для -1s та 1s. Для кожного масиву S він вибирає 1000 ненульових випадкових масивів F довжиною n, що складається з -1,0 або 1, з вірогідністю 1/4, 1/2, / 14 прийому кожного значення. Потім він обчислює внутрішні добутки між F і кожним вікном S довжиною n, поки не знайде ненульовий внутрішній продукт. Він додає 1 до leadingzerocounts
кожної позиції, в якій він знайшов нульовий внутрішній продукт.
Статус
Perl . Уповільнення у 2,7 рази від @tobyink. (У порівнянні з pypy not cpython.)
Дж . 39-кратне прискорення від @Eelvex.
- C . 59 разів пришвидшити @ace.
- Юлія . У 197 разів швидше, не враховуючи час запуску через @ ще одну хвилину. 8,5 разів пришвидшити, включаючи час запуску (у цьому випадку швидше використовувати 4 процесори, ніж 8).
- Фортран . У 438 разів пришвидшити @ напівекзонічний.
- Рпітон . 258 разів пришвидшити @primo.
- C ++ . 508 разів пришвидшити @ilmale.
(Я припинив призначати нові вдосконалення, оскільки вони занадто швидкі, і вона була занадто маленькою.)
Було зазначено, що терміни, що знаходяться нижче секунди, є ненадійними, а також деякі мови мають стартову вартість. Аргумент полягає в тому, що якщо ви хочете включити, ви також повинні включати час компіляції C / C ++ тощо. Ось терміни для найшвидшого коду, кількість ітерацій збільшена до 100 000
- Юлія . 42 секунди за хвилину @ ще одну хвилину.
- C ++ . 14 секунд від @GuySirton.
- Фортран . 14-х років @ напівекзонічні.
- C ++ . 12-х років від @ilmale.
- Рпітон . 18-х років від @primo.
- C ++ . 5s від @Stefan.
Переможець - Стефан!
Наступні виклики розміщені. Як високо ви можете піти? (Виклик кодування + алгоритми) . Це важче.