我应该说我是Swift的新手,我喜欢到目前为止所看到的内容,并且我欣赏编译器只会变得更快.我使用固定大小的多维数组在科学应用程序上进行了大量编码,并且我对将来使用Swift的可能性感兴趣.还是我应该要求Apple为Swift添加真正的多维数组支持?这是我一直在使用的测试代码://// main.swift//// Tests 3 ways of handling 2D arrays in Swift. Test takes a 2D array and calls a routine// that takes each element of an input array and adds the X and Y index values to it and// returns an array with the result.//// Command line arguments: Option Nrpt Nx Ny//// Option is type of array used (1: Swift array of arrays,// 2: Array2D 1D array looking like a 2D array// 3: 1D array used like a 2D array with explicit index calculation)// Nrpt is number of repeats of subroutine call// Nx, Ny are array dimensions.//import Darwin// Array2D comes from http://blog.trolieb.com/trouble-multidimensional-arrays-swift/class Array2D { var cols:Int, rows:Int var matrix: [Int] init(cols:Int, rows:Int) { self.cols = cols self.rows = rows matrix = Array(count:cols*rows, repeatedValue:0) } subscript(col:Int, row:Int) -> Int { get { return matrix[cols * row + col] } set { matrix[cols*row+col] = newValue } } func colCount() -> Int { return self.cols } func rowCount() -> Int { return self.rows }}// Using a 'proper' Swift '2D' array - ie an array of 1D arraysfunc Subr (Input: Array<Array<Int>>, Nx: Int, Ny : Int, inout Output: Array<Array<Int>>) { for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { Output[Iy][Ix] = Input[Iy][Ix] + (Ix + Iy) } }}// Using an Array2D array - wrapping up a 1D array to act as a 2D one.func Subr2d (Input: Array2D, Nx: Int, Ny : Int, inout Output: Array2D) { for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { Output[Ix,Iy] = Input[Ix,Iy] + (Ix + Iy) } }}// Using a 1D Swift array and doing the indexing explicitlyfunc Subr1d (Input: [Int], Nx: Int, Ny: Int, inout Output: [Int]) { for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { Output[Iy * Nx + Ix] = Input[Iy * Nx + Ix] + (Ix + Iy) } }}var Option:Int = 1if let argStr = String.fromCString(C_ARGV[1]) { if let argInt = argStr.toInt() { Option = argInt }}var Nrpt:Int = 100if let argStr = String.fromCString(C_ARGV[2]) { if let argInt = argStr.toInt() { Nrpt = argInt }}var Nx:Int = 2000;if let argStr = String.fromCString(C_ARGV[3]) { if let argInt = argStr.toInt() { Nx = argInt }}var Ny:Int = 10;if let argStr = String.fromCString(C_ARGV[4]) { if let argInt = argStr.toInt() { Ny = argInt }}println("Repeats: \(Nrpt), Array \(Nx) by \(Ny)")switch Option {case 1: println ("Using an ordinary Swift '2D' array of arrays") var array = Array(count:Ny, repeatedValue:Array(count:Nx, repeatedValue:Int())) for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { array[Iy][Ix] = (Ix + Iy) } } var output = Array(count:Ny, repeatedValue:Array(count:Nx, repeatedValue:Int())) let start : UInt64 = mach_absolute_time() for Irpt in 0...Nrpt-1 { Subr(array,Nx,Ny,&output) } let duration : UInt64 = mach_absolute_time() - start check: for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { let Expected = array[Iy][Ix] + (Ix + Iy) if (output[Iy][Ix] != Expected) { println("Error at \(Ix),\(Iy) Got \(output[Iy][Ix]) expected \(Expected)") break check } } } var info : mach_timebase_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info) let total = (duration * UInt64(info.numer) / UInt64(info.denom)) / 1_000_000 println("2D array took:\(total) ms.")case 2: println ("Using the Array2D class") var array2 = Array2D(cols: Nx, rows: Ny) var output2 = Array2D(cols: Nx, rows: Ny) for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { array2[Ix,Iy] = (Ix + Iy) } } println("Timing array2D version") let start2 : UInt64 = mach_absolute_time() for Irpt in 0...Nrpt-1 { Subr2d(array2,Nx,Ny,&output2) } let duration2 : UInt64 = mach_absolute_time() - start2 check: for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { let Expected = array2[Ix,Iy] + (Ix + Iy) if (output2[Ix,Iy] != Expected) { println("Error at \(Ix),\(Iy) Got \(output2[Ix,Iy]) expected \(Expected)") break check } } } var info2 : mach_timebase_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info2) let total2 = (duration2 * UInt64(info2.numer) / UInt64(info2.denom)) / 1_000_000 println("Array2D version took:\(total2) ms.")case 3: println ("Using an a 1D array and handling the indexing explicitly") var array3 = Array(count:Ny * Nx, repeatedValue:Int()) for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { array3[Iy * Nx + Ix] = (Ix + Iy) } } var output3 = Array(count:Ny * Nx, repeatedValue:Int()) let start3 : UInt64 = mach_absolute_time() for Irpt in 0...Nrpt-1 { Subr1d(array3,Nx,Ny,&output3) } let duration3 : UInt64 = mach_absolute_time() - start3 check: for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { let Expected = array3[Iy * Nx + Ix] + (Ix + Iy) if (output3[Iy * Nx + Ix] != Expected) { println("Error at \(Ix),\(Iy) Got \(output3[Iy * Nx + Ix]) expected \(Expected)") break check } } } var info3 : mach_timebase_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info3) let total3 = (duration3 * UInt64(info3.numer) / UInt64(info3.denom)) / 1_000_000 println("1D array took:\(total3) ms.")default: println ("Invalid option code. Must be 1,2, or 3")}解决方案在某种程度上,Apple已经回答了我的问题.我已经有一段时间没有对此进行研究了-的确,甚至还没有使用过Swift.但是我刚刚安装了XCode 9和Swift 4,以为我会看看情况是否有所改变.我必须进行一些快速更改才能构建测试程序,并且我再次尝试过.最重要的是:这三个选项现在几乎都在同一时间运行,而且速度还不错.我认为这是一个了不起的改进,这意味着处理2D数组的标准Swift方法-作为数组的数组-不再有性能损失,并且至少在此测试的基础上,这显然是实现此目的的方法.现在出发.我想这正是每个人都想要的. (我使用-Ounchecked进行了构建,这确实造成了2倍的差异.)与C ++中的等效代码相比,请记住您必须经过一些努力才能将多维数组传递给C ++例程,我认为现在在Swift中编写代码要容易得多.上次我说最快的Swift选项(凌乱的自己做索引"选项)比等效的C ++慢2倍.实际上,我现在看到使用C ++和clang的速度提高了4倍,但是那是因为clang现在似乎已经改善了其本已令人印象深刻的优化(它以最巧妙的方式将向量指令抛在了问题上-以前做到了,但是现在似乎已经摆脱了一些额外的开销).我想这可能会随着时间的流逝而出现在Swift身上.在我看来,重要的是-在此测试的基础上-Swift似乎不再受其数组处理的限制.自从我最初发布此问题以来,clang/C ++的性能提高了2倍,而Swift的性能提高了.这是修改后的代码://// main.swift//// Tests 3 ways of handling 2D arrays in Swift. Test takes a 2D array and calls a routine// that takes each element of an input array and adds the X and Y index values to it and// returns an array with the result.//// Command line arguments: Option Nrpt Nx Ny//// Option is type of array used (1: Swift array of arrays,// 2: Array2D 1D array looking like a 2D array// 3: 1D array used like a 2D array with explicit index calculation)// Nrpt is number of repeats of subroutine call// Nx, Ny are array dimensions.//import Foundation// Array2D comes from http://blog.trolieb.com/trouble-multidimensional-arrays-swift/class Array2D { var cols:Int, rows:Int var matrix: [Int] init(cols:Int, rows:Int) { self.cols = cols self.rows = rows matrix = Array(repeating:0, count:cols*rows) } subscript(col:Int, row:Int) -> Int { get { return matrix[cols * row + col] } set { matrix[cols*row+col] = newValue } } func colCount() -> Int { return self.cols } func rowCount() -> Int { return self.rows }}// Using a 'proper' Swift '2D' array - ie an array of 1D arraysfunc Subr (Input: Array<Array<Int>>, Nx: Int, Ny : Int, Output: inout Array<Array<Int>>) { for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { Output[Iy][Ix] = Input[Iy][Ix] + (Ix + Iy) } }}// Using an Array2D array - wrapping up a 1D array to act as a 2D one.func Subr2d (Input: Array2D, Nx: Int, Ny : Int, Output: inout Array2D) { for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { Output[Ix,Iy] = Input[Ix,Iy] + (Ix + Iy) } }}// Using a 1D Swift array and doing the indexing explicitlyfunc Subr1d (Input: [Int], Nx: Int, Ny: Int, Output: inout [Int]) { for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { Output[Iy * Nx + Ix] = Input[Iy * Nx + Ix] + (Ix + Iy) } }}var Option:Int = 1if (CommandLine.argc > 1) { let argStr = CommandLine.arguments[1] if let argInt = Int(argStr) { Option = argInt }}var Nrpt:Int = 100if (CommandLine.argc > 2) { let argStr = CommandLine.arguments[2] if let argInt = Int(argStr) { Nrpt = argInt }}var Nx:Int = 2000;if (CommandLine.argc > 3) { let argStr = CommandLine.arguments[3] if let argInt = Int(argStr) { Nx = argInt }}var Ny:Int = 10;if (CommandLine.argc > 4) { let argStr = CommandLine.arguments[4] if let argInt = Int(argStr) { Ny = argInt }}print("Repeats: \(Nrpt), Array \(Nx) by \(Ny)")switch Option {case 1: print ("Using an ordinary Swift '2D' array of arrays") var array = Array(repeating:Array(repeating:Int(), count:Nx), count:Ny) for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { array[Iy][Ix] = (Ix + Iy) } } var output = Array(repeating:Array(repeating:Int(), count:Nx), count:Ny) let start : UInt64 = mach_absolute_time() for _ in 0...Nrpt-1 { Subr(Input: array,Nx: Nx,Ny: Ny,Output: &output) } let duration : UInt64 = mach_absolute_time() - start check: for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { let Expected = array[Iy][Ix] + (Ix + Iy) if (output[Iy][Ix] != Expected) { print("Error at \(Ix),\(Iy) Got \(output[Iy][Ix]) expected \(Expected)") break check } } } var info : mach_timebase_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info) let total = (duration * UInt64(info.numer) / UInt64(info.denom)) / 1_000_000 print("2D array took:\(total) ms.")case 2: print ("Using the Array2D class") let array2 = Array2D(cols: Nx, rows: Ny) var output2 = Array2D(cols: Nx, rows: Ny) for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { array2[Ix,Iy] = (Ix + Iy) } } print("Timing array2D version") let start2 : UInt64 = mach_absolute_time() for _ in 0...Nrpt-1 { Subr2d(Input: array2,Nx: Nx,Ny: Ny,Output: &output2) } let duration2 : UInt64 = mach_absolute_time() - start2 check: for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { let Expected = array2[Ix,Iy] + (Ix + Iy) if (output2[Ix,Iy] != Expected) { print("Error at \(Ix),\(Iy) Got \(output2[Ix,Iy]) expected \(Expected)") break check } } } var info2 : mach_timebase_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info2) let total2 = (duration2 * UInt64(info2.numer) / UInt64(info2.denom)) / 1_000_000 print("Array2D version took:\(total2) ms.")case 3: print ("Using an a 1D array and handling the indexing explicitly") var array3 = Array(repeating:Int(), count:Ny * Nx) for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { array3[Iy * Nx + Ix] = (Ix + Iy) } } var output3 = Array(repeating:Int(), count:Ny * Nx) let start3 : UInt64 = mach_absolute_time() for _ in 0...Nrpt-1 { Subr1d(Input: array3,Nx: Nx,Ny: Ny,Output: &output3) } let duration3 : UInt64 = mach_absolute_time() - start3 check: for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { let Expected = array3[Iy * Nx + Ix] + (Ix + Iy) if (output3[Iy * Nx + Ix] != Expected) { print("Error at \(Ix),\(Iy) Got \(output3[Iy * Nx + Ix]) expected \(Expected)") break check } } } var info3 : mach_timebase_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info3) let total3 = (duration3 * UInt64(info3.numer) / UInt64(info3.denom)) / 1_000_000 print("1D array took:\(total3) ms.")default: print ("Invalid option code. Must be 1,2, or 3")}I have a fixed size multi-dimensional array of numbers (floats, usually, but ints in my example code to avoid being distracted by conversion overheads), and I want to manipulate it efficiently. Swift doesn't provide multi-dimensional arrays as such, but you can get the effect through an array of 1D arrays. However, these seem to be very, very slow. Is there a better way?I have a test problem (which I've used to benchmark other languages) where I pass two 2D arrays to a subroutine which sets each element of one to the corresponding element of the other plus the sum of the two index values. (Which means what happens to each element depends on its coordinates, which is what happens in most real-world cases.)I've compiled using the -Ounchecked flag.Option 1: Using an array of 1D arrays, I get very slow performance.10 passes took 1.5 seconds.Option 2: Using the rather neat idea in http://blog.trolieb.com/trouble-multidimensional-arrays-swift where an Array2D class uses an underlying 1D array and implements subscript() to make it look like a 2D array, things speed up a lot (2 orders of magnitude):1000 passes took 1.0 secondsOption 3: Falling back on the very awkward sort of code one used to use in C, where you use a 1D array and do the index = (row * columns) + column calculation explicitly, things speed up yet again (not quite 2 orders of magnitude)100000 passes took 3.6 seconds.Option 3 is within a factor 2 of what I get out of the equivalent C code compiled with -O3 in clang, so is fine for a early-days compiler. The problem is that it's really ugly, awkward and error prone. There are tricks one can use in C, like allocating arrays of pointers to the start of each line (Numerical Recipes in C does this) to allow you to use a 2D syntax for arrays, and with an object-oriented C you can make this quite elegant as well as efficient. My question is really is there a way in Swift to get code like array[Iy][Ix] (or array[Iy,Ix] or whatever, as opposed to array[Iy*Ny + Ix]) to run fast?I should say that I'm very new to Swift, and I like what I've seen so far, and I appreciate that compilers will only get faster. I do a lot of coding on scientific applications using fixed size multi-dimensional arrays, and I'm interested in the possibility of using Swift some time in the future. Or should I be asking Apple to add real multi-dimensional array support to Swift?Here's the test code I've been using://// main.swift//// Tests 3 ways of handling 2D arrays in Swift. Test takes a 2D array and calls a routine// that takes each element of an input array and adds the X and Y index values to it and// returns an array with the result.//// Command line arguments: Option Nrpt Nx Ny//// Option is type of array used (1: Swift array of arrays,// 2: Array2D 1D array looking like a 2D array// 3: 1D array used like a 2D array with explicit index calculation)// Nrpt is number of repeats of subroutine call// Nx, Ny are array dimensions.//import Darwin// Array2D comes from http://blog.trolieb.com/trouble-multidimensional-arrays-swift/class Array2D { var cols:Int, rows:Int var matrix: [Int] init(cols:Int, rows:Int) { self.cols = cols self.rows = rows matrix = Array(count:cols*rows, repeatedValue:0) } subscript(col:Int, row:Int) -> Int { get { return matrix[cols * row + col] } set { matrix[cols*row+col] = newValue } } func colCount() -> Int { return self.cols } func rowCount() -> Int { return self.rows }}// Using a 'proper' Swift '2D' array - ie an array of 1D arraysfunc Subr (Input: Array<Array<Int>>, Nx: Int, Ny : Int, inout Output: Array<Array<Int>>) { for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { Output[Iy][Ix] = Input[Iy][Ix] + (Ix + Iy) } }}// Using an Array2D array - wrapping up a 1D array to act as a 2D one.func Subr2d (Input: Array2D, Nx: Int, Ny : Int, inout Output: Array2D) { for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { Output[Ix,Iy] = Input[Ix,Iy] + (Ix + Iy) } }}// Using a 1D Swift array and doing the indexing explicitlyfunc Subr1d (Input: [Int], Nx: Int, Ny: Int, inout Output: [Int]) { for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { Output[Iy * Nx + Ix] = Input[Iy * Nx + Ix] + (Ix + Iy) } }}var Option:Int = 1if let argStr = String.fromCString(C_ARGV[1]) { if let argInt = argStr.toInt() { Option = argInt }}var Nrpt:Int = 100if let argStr = String.fromCString(C_ARGV[2]) { if let argInt = argStr.toInt() { Nrpt = argInt }}var Nx:Int = 2000;if let argStr = String.fromCString(C_ARGV[3]) { if let argInt = argStr.toInt() { Nx = argInt }}var Ny:Int = 10;if let argStr = String.fromCString(C_ARGV[4]) { if let argInt = argStr.toInt() { Ny = argInt }}println("Repeats: \(Nrpt), Array \(Nx) by \(Ny)")switch Option {case 1: println ("Using an ordinary Swift '2D' array of arrays") var array = Array(count:Ny, repeatedValue:Array(count:Nx, repeatedValue:Int())) for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { array[Iy][Ix] = (Ix + Iy) } } var output = Array(count:Ny, repeatedValue:Array(count:Nx, repeatedValue:Int())) let start : UInt64 = mach_absolute_time() for Irpt in 0...Nrpt-1 { Subr(array,Nx,Ny,&output) } let duration : UInt64 = mach_absolute_time() - start check: for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { let Expected = array[Iy][Ix] + (Ix + Iy) if (output[Iy][Ix] != Expected) { println("Error at \(Ix),\(Iy) Got \(output[Iy][Ix]) expected \(Expected)") break check } } } var info : mach_timebase_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info) let total = (duration * UInt64(info.numer) / UInt64(info.denom)) / 1_000_000 println("2D array took:\(total) ms.")case 2: println ("Using the Array2D class") var array2 = Array2D(cols: Nx, rows: Ny) var output2 = Array2D(cols: Nx, rows: Ny) for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { array2[Ix,Iy] = (Ix + Iy) } } println("Timing array2D version") let start2 : UInt64 = mach_absolute_time() for Irpt in 0...Nrpt-1 { Subr2d(array2,Nx,Ny,&output2) } let duration2 : UInt64 = mach_absolute_time() - start2 check: for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { let Expected = array2[Ix,Iy] + (Ix + Iy) if (output2[Ix,Iy] != Expected) { println("Error at \(Ix),\(Iy) Got \(output2[Ix,Iy]) expected \(Expected)") break check } } } var info2 : mach_timebase_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info2) let total2 = (duration2 * UInt64(info2.numer) / UInt64(info2.denom)) / 1_000_000 println("Array2D version took:\(total2) ms.")case 3: println ("Using an a 1D array and handling the indexing explicitly") var array3 = Array(count:Ny * Nx, repeatedValue:Int()) for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { array3[Iy * Nx + Ix] = (Ix + Iy) } } var output3 = Array(count:Ny * Nx, repeatedValue:Int()) let start3 : UInt64 = mach_absolute_time() for Irpt in 0...Nrpt-1 { Subr1d(array3,Nx,Ny,&output3) } let duration3 : UInt64 = mach_absolute_time() - start3 check: for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { let Expected = array3[Iy * Nx + Ix] + (Ix + Iy) if (output3[Iy * Nx + Ix] != Expected) { println("Error at \(Ix),\(Iy) Got \(output3[Iy * Nx + Ix]) expected \(Expected)") break check } } } var info3 : mach_timebase_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info3) let total3 = (duration3 * UInt64(info3.numer) / UInt64(info3.denom)) / 1_000_000 println("1D array took:\(total3) ms.")default: println ("Invalid option code. Must be 1,2, or 3")} 解决方案 In a way, Apple have answered my question. I've not looked at this for a while now - and, indeed, haven't even been using Swift. But I've just installed XCode 9 and Swift 4, and thought I'd see if things have changed. I had to make some quick changes to get the test program to build, and I've tried it again.Bottom line: All three options run in about the same time now, and that speed is not bad at all. I think that's a remarkable improvement, and it means that the standard Swift way of handling a 2D array - as an array of arrays - no longer has a performance penalty, and, at least on the basis of this test, is clearly the way to go now. Which is exactly what I think everyone would want. (I've built with -Ounchecked, which does make about a factor 2 difference.)Compared to the equivalent code in C++, bearing in mind that you have to go through some hoops to pass multi-dimensional arrays to C++ routines, I think this is now much easier to code in Swift. Last time I said the fastest Swift option (the messy 'do the indexing yourself' option) ran only a factor 2 slower than the equivalent C++. Actually, I now see a factor 4 speed-up from using C++ and clang, but that's because clang now seems to have improved its already impressive optimisation (it throws vector instructions at the problem in a most ingenious way - it did that before, but now it seems to have gotten rid of some additional overheads). That's something I imagine may come to Swift with time; the important thing to my mind is that - again, on the basis of this one test - Swift no longer seems to be restricted by its array handling. Since I originally posted this question, clang/C++ has improved by a factor 2, but Swift has improved out of sight.Here's the revised code://// main.swift//// Tests 3 ways of handling 2D arrays in Swift. Test takes a 2D array and calls a routine// that takes each element of an input array and adds the X and Y index values to it and// returns an array with the result.//// Command line arguments: Option Nrpt Nx Ny//// Option is type of array used (1: Swift array of arrays,// 2: Array2D 1D array looking like a 2D array// 3: 1D array used like a 2D array with explicit index calculation)// Nrpt is number of repeats of subroutine call// Nx, Ny are array dimensions.//import Foundation// Array2D comes from http://blog.trolieb.com/trouble-multidimensional-arrays-swift/class Array2D { var cols:Int, rows:Int var matrix: [Int] init(cols:Int, rows:Int) { self.cols = cols self.rows = rows matrix = Array(repeating:0, count:cols*rows) } subscript(col:Int, row:Int) -> Int { get { return matrix[cols * row + col] } set { matrix[cols*row+col] = newValue } } func colCount() -> Int { return self.cols } func rowCount() -> Int { return self.rows }}// Using a 'proper' Swift '2D' array - ie an array of 1D arraysfunc Subr (Input: Array<Array<Int>>, Nx: Int, Ny : Int, Output: inout Array<Array<Int>>) { for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { Output[Iy][Ix] = Input[Iy][Ix] + (Ix + Iy) } }}// Using an Array2D array - wrapping up a 1D array to act as a 2D one.func Subr2d (Input: Array2D, Nx: Int, Ny : Int, Output: inout Array2D) { for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { Output[Ix,Iy] = Input[Ix,Iy] + (Ix + Iy) } }}// Using a 1D Swift array and doing the indexing explicitlyfunc Subr1d (Input: [Int], Nx: Int, Ny: Int, Output: inout [Int]) { for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { Output[Iy * Nx + Ix] = Input[Iy * Nx + Ix] + (Ix + Iy) } }}var Option:Int = 1if (CommandLine.argc > 1) { let argStr = CommandLine.arguments[1] if let argInt = Int(argStr) { Option = argInt }}var Nrpt:Int = 100if (CommandLine.argc > 2) { let argStr = CommandLine.arguments[2] if let argInt = Int(argStr) { Nrpt = argInt }}var Nx:Int = 2000;if (CommandLine.argc > 3) { let argStr = CommandLine.arguments[3] if let argInt = Int(argStr) { Nx = argInt }}var Ny:Int = 10;if (CommandLine.argc > 4) { let argStr = CommandLine.arguments[4] if let argInt = Int(argStr) { Ny = argInt }}print("Repeats: \(Nrpt), Array \(Nx) by \(Ny)")switch Option {case 1: print ("Using an ordinary Swift '2D' array of arrays") var array = Array(repeating:Array(repeating:Int(), count:Nx), count:Ny) for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { array[Iy][Ix] = (Ix + Iy) } } var output = Array(repeating:Array(repeating:Int(), count:Nx), count:Ny) let start : UInt64 = mach_absolute_time() for _ in 0...Nrpt-1 { Subr(Input: array,Nx: Nx,Ny: Ny,Output: &output) } let duration : UInt64 = mach_absolute_time() - start check: for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { let Expected = array[Iy][Ix] + (Ix + Iy) if (output[Iy][Ix] != Expected) { print("Error at \(Ix),\(Iy) Got \(output[Iy][Ix]) expected \(Expected)") break check } } } var info : mach_timebase_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info) let total = (duration * UInt64(info.numer) / UInt64(info.denom)) / 1_000_000 print("2D array took:\(total) ms.")case 2: print ("Using the Array2D class") let array2 = Array2D(cols: Nx, rows: Ny) var output2 = Array2D(cols: Nx, rows: Ny) for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { array2[Ix,Iy] = (Ix + Iy) } } print("Timing array2D version") let start2 : UInt64 = mach_absolute_time() for _ in 0...Nrpt-1 { Subr2d(Input: array2,Nx: Nx,Ny: Ny,Output: &output2) } let duration2 : UInt64 = mach_absolute_time() - start2 check: for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { let Expected = array2[Ix,Iy] + (Ix + Iy) if (output2[Ix,Iy] != Expected) { print("Error at \(Ix),\(Iy) Got \(output2[Ix,Iy]) expected \(Expected)") break check } } } var info2 : mach_timebase_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info2) let total2 = (duration2 * UInt64(info2.numer) / UInt64(info2.denom)) / 1_000_000 print("Array2D version took:\(total2) ms.")case 3: print ("Using an a 1D array and handling the indexing explicitly") var array3 = Array(repeating:Int(), count:Ny * Nx) for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { array3[Iy * Nx + Ix] = (Ix + Iy) } } var output3 = Array(repeating:Int(), count:Ny * Nx) let start3 : UInt64 = mach_absolute_time() for _ in 0...Nrpt-1 { Subr1d(Input: array3,Nx: Nx,Ny: Ny,Output: &output3) } let duration3 : UInt64 = mach_absolute_time() - start3 check: for Iy in 0...Ny-1 { for Ix in 0...Nx-1 { let Expected = array3[Iy * Nx + Ix] + (Ix + Iy) if (output3[Iy * Nx + Ix] != Expected) { print("Error at \(Ix),\(Iy) Got \(output3[Iy * Nx + Ix]) expected \(Expected)") break check } } } var info3 : mach_timebase_info = mach_timebase_info(numer: 0, denom: 0) mach_timebase_info(&info3) let total3 = (duration3 * UInt64(info3.numer) / UInt64(info3.denom)) / 1_000_000 print("1D array took:\(total3) ms.")default: print ("Invalid option code. Must be 1,2, or 3")} 这篇关于在Swift中访问多维数组的最有效方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-16 06:53