Это продолжение того, насколько медленно работает 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]
Вы должны использовать случайное начальное число в своем коде, и любой генератор случайных чисел, который достаточно хорош, чтобы дать ответы, близкие к приведенным выше, будет принят.
Моя машина Время будет запущено на моей машине. Это стандартная установка Ubuntu на восьмиъядерный процессор AMD FX-8350. Это также означает, что мне нужно иметь возможность запускать ваш код.
Объяснение кода
Этот код выполняет итерацию по всем массивам S длиной n + m-1, которые составлены на -1 с и 1 с. Для каждого массива S он выбирает 1000 ненулевых случайных массивов F длины n, составленных из -1,0 или 1 с вероятностью 1/4, 1/2, / 14 принятия каждого значения. Затем он вычисляет внутренние произведения между F и каждым окном S длины n, пока не найдет ненулевое внутреннее произведение. Он добавляет 1 к leadingzerocounts
каждому найденному положению с нулевым внутренним произведением.
Статус
Perl . Замедление в 2,7 раза от @tobyink. (По сравнению с pypy, а не cpython.)
Дж . Ускорение в 39 раз @Eelvex.
- C . Ускорение в 59 раз
- Джулия . В 197 раз быстрее, не включая время запуска на одну минуту больше. Ускорение в 8,5 раз, включая время запуска (в данном случае быстрее при использовании 4 процессоров, чем 8).
- Фортран . Ускорение в 438 раз при @ полуэкстремальном.
- Rpython . Ускорение в 258 раз благодаря @primo.
- С ++ . @Ilmale ускорил в 508 раз.
(Я перестал рассчитывать новые улучшения, потому что они слишком быстрые, а iters были слишком малы.)
Было отмечено, что время ниже секунды ненадежно, а также некоторые языки имеют начальную стоимость. Аргументом является то, что если вы хотите включить это, вы должны также включить время компиляции C / C ++ и т. Д. Вот время для самого быстрого кода с числом итераций, увеличенным до 100 000.
- Джулия . 42 секунды на @ еще одну минуту.
- С ++ . 14 секунд @GuySirton.
- Фортран . 14s от @ полу-внешности.
- С ++ . 12s @ilmale.
- Rpython . 18s @primo.
- С ++ . 5s @Stefan.
Победитель .. Стефан!
Последующий вызов опубликован. Как высоко вы можете пойти? (Задача кодирования + алгоритмы) . Этот сложнее.