свифт производительности бета: сортировка массивов


я реализует алгоритм в swift beta и заметил, что выступление было очень плохим. покопавшись глубже, я понял, что одним из узких мест было как-то просто, как сортировка массивов. в соответствующей части-это здесь:

let n = 1000000var x =  [int](repeating: 0, count: n)for i in 0..<n {    x[i] = random()}// start clock herelet y = sort(x)// stop clock here
0.06s

в c , подобная операция занимает на моем компьютере.

0.6s

в python, это занимает (нет трюков, только y = отсортированный(x) для списка целых чисел).

6s

в swift это займет, если я скомпилировать его с помощью следующей команды:

xcrun swift -o3 -sdk `xcrun --show-sdk-path --sdk macosx`
88s

и это если я скомпилировать его с помощью следующей команды:

xcrun swift -o0 -sdk `xcrun --show-sdk-path --sdk macosx`

тайминги в xcode с "освобождение" и "отладка" строит подобные.

что здесь неправильно? я могу понять некоторую потерю производительности по сравнению с c , а не 10-кратное замедление по сравнению с чистом python.

edit:-o3-ofast-ofastdisabled the checks for integer overflows and array indexing overflows-ofast

погода заметил, что изменение делает этот код работать почти так же быстро, как версия c! однако, изменения семантики языка много — в моем тестировании, то это . например, следующий код swift работает тихо без сбоев (и печатает какую-то фигню):

let n = 10000000print(n*n*n*n*n)let x =  [int](repeating: 10, count: n)print(x[n])
-ofast-ftrapv

так это не то, что мы хотим

отсюда вопрос: как мы можем получить разумную производительность в свифт без потери сети безопасности?

edit 2:

я сделал некоторые бенчмаркинг, с очень простой петли вдоль линий

for i in 0..<n {    x[i] = x[i] ^ 12345678}

(здесь операции xor есть просто так, что я могу более легко найти соответствующие петли в ассемблерный код. я попытался поднять действием, которое легко обнаружить, но также "безобидно" в том смысле, что он не должен требовать каких-либо проверок, связанных в целое переполнение.)

-o3-ofast

опять же, есть огромная разница в производительности между и . поэтому я посмотрел на ассемблерный код:

  • with -ofast i get pretty much what i would expect. the relevant part is a loop with 5 machine language instructions.

  • with -o3 i get something that was beyond my wildest imagination. the inner loop spans 88 lines of assembly code. i did not try to understand all of it, but the most suspicious parts are 13 invocations of "callq _swift_retain" and another 13 invocations of "callq _swift_release". that is, 26 subroutine calls in the inner loop!

  • edit 3:

    в комментариях, ферруччо попросил критериев, которые являются справедливыми в том смысле, что они не полагаются на встроенные функции (например, сортировки). я думаю, что следующая программа-это очень хороший пример:

    let n = 10000var x = [int](repeating: 1, count: n)for i in 0..<n {    for j in 0..<n {        x[i] = x[j]    }}

    нет никакой арифметики, поэтому нам не нужно беспокоиться о переполнения целочисленных значений. единственное, что мы сделать, это просто большой массив ссылок. а результаты здесь—свифт -о3 проиграет с коэффициентом почти на 500 по сравнению с -ofast:

  • c++ -o3: 0.05 s
  • c++ -o0: 0.4 s
  • java: 0.2 s
  • python with pypy: 0.5 s
  • python: 12 s
  • swift -ofast: 0.05 s
  • swift -o3: 23 s
  • swift -o0: 443 s
  • x[i] ^= x[j]x[0]

    (если вы обеспокоены тем, что компилятор может оптимизировать таким полностью петли, вы можете изменить его, например , и добавить оператор print, который выводит . это ничего не меняет

    much

    и да, здесь реализация python был глупым чисто реализацию python с перечнем объектов и вложенных циклов for. она должна быть медленнее, чем неоптимизированный свифт. похоже, что-то серьезно сломано с быстрой и индексации массива.

    edit 4:

    эти вопросы (а также некоторые другие проблемы с производительностью), кажется, была исправлена в xcode 6 бета 5.

    для сортировки, теперь у меня есть следующие тайминги:

  • clang++ -o3: 0.06 s
  • swiftc -ofast: 0.1 s
  • swiftc -o: 0.1 s
  • swiftc: 4 s
  • для вложенных циклов:

  • clang++ -o3: 0.06 s
  • swiftc -ofast: 0.3 s
  • swiftc -o: 0.4 s
  • swiftc: 540 s
  • -ofast-ounchecked-o

    кажется, что нет причин не использовать небезопасные (а.к.а. )