Julia中的时间效率时钟阵列旋转



我正在做Hackerearth的挑战,第一个挑战是简单的顺时针数组旋转。因此,给定一个数组,例如:

arr = "1 2 3 4 5"

如果你旋转它(顺时针(两步,那么你会得到以下结果:

arr = "4 5 1 2 3"

因此,我能够构建一个这样做的算法,并且我还使用了Julias的原生circshift函数,但我仍然不够高效。每次测试允许的最长时间是1秒,我目前的实现需要1.5秒

我的代码如下:

test_cases = readline() #read the amount of test cases
tests = test_cases[1:end]
tests = string(tests)
tests = parse(Int8, tests)
for i in 1:tests
second_line = readline() #reads the size of the array and the steps
third_line = readline() #read the actual array

function solution(second_line, third_line)
#first we separate the number of the array from the steps to rotate
len_steps = split(second_line, " ")
len = parse(Int8, len_steps[1])
steps = parse(Int8, len_steps[2])

#secondly we separate the third line into the actual array
line = split(third_line, " ")

#if steps > length, get the modulus. Else, do the normal stepping.
if steps > len
steps = steps%len
end

#now we start filling out the new array. This is not as effective.
return join(vcat(line[(len-steps+1):end], line[1:(len-steps)]), " ")
end
test = solution(second_line, third_line)
print(test)
println(" ")
end

这是该算法的当前版本,它使用了Julias的一些本地工具。我之前的解释有一个for循环,这只会让情况变得更糟。正如我所提到的,circshift也没有削减它,那么我该如何改进它以提高它的效率呢?

下面我分享了一个输入的示例,但完整的文件在pastebin上。

13
384 886
655497 374005 129593 387055 595396 152862 251289 702661 595772 811057 321410 686329 174533 17836 235740 330576 568552 472246 881591 761168 161847 121659 617522 747110 345962 187723 773947 850345 578189 611862 78672 844128 596309 716697 333193 293716 480001 584482 606819 177783 107991 30239 474554 790957 556508 710294 731975 227070 792983 715576 598681 56840 837236 318213 414392 793640 505936 798781 745995 186135 512654 824667 640706 719405 253816 75909 623563 733817 270834 840825 522042 378825 871064 98607 780224 140024 419343 614210 875527 822768 431796 576218 879608 879474 504873 396011 775124 112819 296802 623130 807386 419898 160249 550102 749746 414066 236454 475319 758325 117730 418154 382378 106997 1671 91427 887222 650127 121212 603442 238106 45991 645680 424766 536041 627165 31649 542494 504299 652900 449739 737871 562297 869637 131 722841 331835 24639 569737 417597 393406 687467 446193 386226 794465 58306 477653 394139 708434 209308 99591 556982 255299 355713 83759 791340 84888 115408 435845 199630 768309 496026 547943 43058 78115 158516 376341 409951 183155 48089 827548 187004 345998 375751 573230 242473 44500 152894 247054 752934 870634 855077 411926 227943 312801 106127 629725 397689 221536 676012 207761 600287 274048 755705 253787 352164 16231 630128 762115 707819 678217 302115 894823 634658 288308 570063 877131 332808 333399 226196 696184 306043 183283 718553 144428 106526 824680 774154 114658 656658 162618 322419 867387 436667 688566 223184 399273 315240 853313 771830 125069 243982 175955 630334 878640 74705 810839 468224 17956 246249 304862 324582 162734 98587 653577 815595 205114 580268 302201 319772 847368 464819 252633 816766 511928 43210 650392 13211 358450 605715 785041 93961 460140 571438 724295 440790 256586 637144 519456 274542 493835 824318 209566 267012 533348 863144 184617 738462 155864 97260 668676 105242 562079 23319 532450 176018 574961 284853 697661 35421 501010 584713 637814 63160 766593 464119 503951 125189 711706 633849 10173 815983 560178 219740 185005 195536 693326 878054 544440 849190 77324 315126 56442 249846 846877 199335 36306 523849 484188 733967 169712 87208 31132 417969 150369 797726 492530 264762 533357 306246 621 153973 732672 171241 882145 528119 875209 677481 508184 521659 628681 195950 447227 295565 56238 6557 494900 92544 140848 589530 436954 818992 676739 468086 338971 437550 876254 831502 702312 511622 748190 313375 665595 582872 95059 649750 213002 72278 39683 331628 204380 668364 138020 262049 574371 194259 268606 171282 795235 409454 371254 334199 838889 150003 802286 279870 197995 780550 213382 510749 4624 63583 824125 280661 256897

使用ShiftedArrays:

using ShiftedArrays, BenchmarkTools
a=collect(1:10_000_000)

现在:

julia> CircShiftedVector(a, 3)
10000000-element CircShiftedVector{Int64, Vector{Int64}}:
9999998
9999999
10000000
1
2
3
⋮
9999995
9999996
9999997

这是不分配的,所以时间成本是一纳秒:

julia> @btime CircShiftedVector($a, 3);
1.300 ns (0 allocations: 0 bytes)

circshift速度非常快,您应该使用它。

目前还不清楚您想在这里测量什么,但很清楚,代码中几乎100%的时间都花在了文件读取、字符串解析和打印上,这还没有考虑在全局范围内工作所引起的性能问题。

因此,首先,您应该将代码封装在函数中。手册中的性能提示1(https://docs.julialang.org/en/v1/manual/performance-tips/)是";避免全局变量";。这对表现影响很大。将代码封装在函数中,并确保所有变量都作为输入参数传递,而不是依赖于全局变量。

至于circshift的性能,考虑一下:

1.7.0> using BenchmarkTools
1.7.0> x = rand(1000);
1.7.0> @btime circshift($x, 500);
552.604 ns (1 allocation: 7.94 KiB)  # <- nanoseconds!
1.7.0> @btime join(circshift($x, 500), " ");
135.700 μs (2013 allocations: 461.98 KiB)  # <- microseconds!

不到0.5%的运行时间用于circshift,然后我忽略了从文件中读取和解析数据的部分,这可能需要更长的时间。我非常确信circshift在您的代码中所占的时间远小于1/1000。

换句话说,使用circshift,然后花时间改进代码其他部分的性能(并阅读性能提示;(

最新更新