That sounds interesting. Would you mind making that pitch on swift-evolution? I 
just barely understood what you said :/

> On Nov 22, 2016, at 07:46 , Hooman Mehr <hoo...@mac.com> wrote:
> 
> It is good to know that 
> 
> extension Array where Element == Double { }
> 
> will work pretty soon with Swift 3.1.
> 
> Back to reduce(0,+):
> 
> If we get specialized instance for a reduce(0,+), so that it is known that 
> “+” is a (Double, Double)->Double function, LLVM’s auto-vectorization should 
> be able to optimize it for the CPU’s vector unit. In theory, it should be 
> possible to add additional optimizers to LLVM layer to use other hardware or 
> numeric libraries for that purpose, but I don’t think it would be a 
> Swift-specific thing.
> 
> Swift’s generics still has a long way to go. Since they are aiming for ABI 
> stability by Swift 4.0, and there isn’t much time left, I don’t think many of 
> the bigger generics improvements fit with the current Swift evolution 
> discussions, although they could have huge impact on standard library (hence 
> the ABI stability). 
> 
> One thing that might be worth discussing on Swift evolution and can 
> potentially make it to standard library and Swift 4.0 is adding a common 
> protocol for array-like types that have (or can have) contiguous buffers so 
> that manually vectorizing operations on their elements becomes easier and 
> cleaner.
> 
> At the moment, we can manually define a protocol that extends 
> RandomAccessCollection and provides `withUnsafeBufferPointer` and then 
> declare the conformance of all of the standard library array variants to it 
> so that we can provide a single generic sum global function for summing all 
> of them using vDSP. This protocol may be worth adding to the standard library.
> 
>> On Nov 21, 2016, at 7:05 PM, Rick Mann <rm...@latencyzero.com> wrote:
>> 
>> Thanks, Hooman. Is it worth posting on swift-evolution the question about 
>> specializing something like reduce(0, +) (it's complicated because it would 
>> mean specializing reduce() based on both the type and the closure passed, 
>> and that seems like something that would be difficult to specify concisely 
>> in the syntax).
>> 
>>> On Nov 21, 2016, at 18:29 , Hooman Mehr <hoo...@mac.com> wrote:
>>> 
>>> This is not possible in Swift 3.0. Swift 4.0 will improve things with 
>>> conditional conformances.
>>> 
>>> For now, the best solution is using global functions instead of extending 
>>> types or protocols.
>>> 
>>> For example you can do this now:
>>> 
>>> extension Array where Element: FloatingPoint {
>>> 
>>>   func sum() -> Element {
>>>       guard count > 0 else { return 0 }
>>>       switch self[0] {
>>>       case is Double:
>>>           var result = Double()
>>>           vDSP_sveD(unsafeBitCast(self, to: Array<Double>.self), 1, 
>>> &result, vDSP_Length(count))
>>>           print("vDSP")
>>>           return unsafeBitCast(result, to: Element.self)
>>>       case is Float:
>>>           var result = Float()
>>>           vDSP_sve(unsafeBitCast(self, to: Array<Float>.self), 1, &result, 
>>> vDSP_Length(count))
>>>           print("vDSP")
>>>           return unsafeBitCast(result, to: Element.self)
>>>       default:
>>>           print("default")
>>>           return reduce(0, +)
>>>       }
>>>   }
>>> }
>>> 
>>> But this is not very efficient, especially if it is defined in another 
>>> module, which limits optimizations.
>>> 
>>> Instead, a family of overloaded global functions gives you the most 
>>> coverage and best performance, at the expense of repetition and boilerplate 
>>> code:
>>> 
>>> func sum<S: Sequence>(_ sequence: S) -> S.Iterator.Element where 
>>> S.Iterator.Element: Integer {
>>>   var result: S.Iterator.Element = 0
>>>   for element in sequence { result += element }
>>>   return result
>>> }
>>> 
>>> func sum<S: Sequence>(_ sequence: S) -> S.Iterator.Element where 
>>> S.Iterator.Element: FloatingPoint {
>>>   var result: S.Iterator.Element = 0
>>>   for element in sequence { result += element }
>>>   return result
>>> }
>>> 
>>> func sum(_ array: Array<Double>) -> Double {
>>>   var result = Double()
>>>   vDSP_sveD(array, 1, &result, vDSP_Length(array.count))
>>>   return result
>>> }
>>> 
>>> func sum(_ array: ContiguousArray<Double>) -> Double {
>>>   var result = Double()
>>>   array.withUnsafeBufferPointer { vDSP_sveD($0.baseAddress!, 1, &result, 
>>> vDSP_Length(array.count)) }
>>>   return result
>>> }
>>> 
>>> func sum(_ array: ArraySlice<Double>) -> Double {
>>>   var result = Double()
>>>   array.withUnsafeBufferPointer { vDSP_sveD($0.baseAddress!, 1, &result, 
>>> vDSP_Length(array.count)) }
>>>   return result
>>> }
>>> 
>>> func sum(_ array: Array<Float>) -> Float {
>>>   var result = Float()
>>>   vDSP_sve(array, 1, &result, vDSP_Length(array.count))
>>>   return result
>>> }
>>> 
>>> func sum(_ array: ContiguousArray<Float>) -> Float {
>>>   var result = Float()
>>>   array.withUnsafeBufferPointer { vDSP_sve($0.baseAddress!, 1, &result, 
>>> vDSP_Length(array.count)) }
>>>   return result
>>> }
>>> 
>>> func sum(_ array: ArraySlice<Float>) -> Float {
>>>   var result = Float()
>>>   array.withUnsafeBufferPointer { vDSP_sve($0.baseAddress!, 1, &result, 
>>> vDSP_Length(array.count)) }
>>>   return result
>>> }
>>> 
>>> The above code covers summing any integer or floating point sequence of 
>>> numbers, while being accelerated for Float and Double array types (Array, 
>>> ContiguousArray and ArraySlice)
>>> 
>>> 
>>>> On Nov 21, 2016, at 4:32 PM, Rick Mann via swift-users 
>>>> <swift-users@swift.org> wrote:
>>>> 
>>>> My googling is not turning up an answer that works in Xcode 8.1. I'd like 
>>>> to do this:
>>>> 
>>>> 
>>>> import Accelerate
>>>> 
>>>> extension
>>>> Array
>>>>    where Element == Double
>>>> {
>>>>    func
>>>>    sum()
>>>>            -> Double
>>>>    {
>>>>            var result: Double = 0.0
>>>>            vDSP_sveD(self, 1, &result, vDSP_Length(self.count))
>>>>            return result
>>>>    }
>>>> }
>>>> 
>>>> But I get "same-type requirement makes generic parameter 'Element' 
>>>> non-generic."
>>>> 
>>>> Also, will there ever be any way to specialize something like
>>>> 
>>>>    let numbers: [Double] = ...
>>>>    let sum = numbers.reduce(0.0, +)
>>>> 
>>>> Into a call to vDSP_sveD()? Would it require compiler optimizations for 
>>>> Accelerate?
>>>> 
>>>> Thanks!
>>>> 
>>>> -- 
>>>> Rick Mann
>>>> rm...@latencyzero.com
>>>> 
>>>> 
>>>> _______________________________________________
>>>> swift-users mailing list
>>>> swift-users@swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-users
>>> 
>> 
>> 
>> -- 
>> Rick Mann
>> rm...@latencyzero.com
>> 
>> 
> 


-- 
Rick Mann
rm...@latencyzero.com


_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to