大多数浏览器和
Developer App 均支持流媒体播放。
-
使用 Accelerate 提高性能并纳入加密档案
Accelerate Framework 可帮助您进行大规模数学计算和图像计算,这些操作都经过高性能、低能耗优化。探索 Accelerate 及其“基础神经网络子程序”库的最新更新,包括附加层、激活函数和改进的优化器支持。查看 simd.h 的改进,包括更好的 C++ 模板支持。探索 Apple Encrypted Archive 支持,它是 Apple Archive 的扩展,其中结合了压缩与强大的加密和数字签名功能。同时,了解如何在不影响性能的情况下确保数据安全。
资源
相关视频
WWDC19
-
下载
♪低音音乐播放♪ ♪ 乔纳森霍格:哈啰 欢迎收看这段 关于加速和相关框架的内容 我是乔纳森 在Apple的向量和数字团队工作 今天我要简单地向大家介绍 加速框架 之后会再告诉各位 我们机器学习库的新内容 BNNS 接着会讲到simd.h的改良 并且介绍Apple文档库 和我们新的Apple加密文档容器 让我们先简单地浏览 加速框架 加速框架在所有Apple平台上 提供高性能的数字计算 包括macOS、iOS、iPadOS watchOS和Apple tvOS 加速框架也能在搭载 Apple 芯片的 Mac 和最近的iPhone和iPad装置中 存取机器学习加速器 要使用这个硬件的方式只能通过 直接调用加速框架 或是通过像Core ML这种高层次框架 加速框架由好几个部分组成 vDSP提供信号处理的原语 例如离散傅立叶变换 和快速傅立叶变换例程 vImage提供图像处理的例程 例如格式转换和卷积 vForce提供向量化的超越函数 例如正弦和余弦 BLAS和LAPACK提供 标准稠密矩阵代数例程的 高性能植入 而稀疏BLAS和我们的稀疏解算器 提供类似的功能给稀疏矩阵 最后 BNNS提供支持机器学习 今天我也要跟大家介绍 一些相关的框架 simd.h提供小向量和矩阵的计算 例如那些包裹在图形程序设计的内容 同时Compression和AppleArchive 提供支持非破坏性数据压缩 要使用这些框架 只需要加入相关的include命令 或将陈述输入你的编码内 并且将框架加到你的Xcode项目中 现在 让我更详细的介绍BNNS BNNS代表基础神经网络子程序 并且在CPU上提供机器学习的 性能原语 对于那些不熟悉 Apple机器学习生态系统的人 这张图说明了目前的情形 有三个主要的硬件区块 CPU 它包含了我刚刚提过的 机器学习加速器 GPU 和独立的神经引擎 BNNS在CPU上提供性能原语 和MPS在GPU上提供性能原语 是用同样的方法 在这一层上面 还有几个框架 会在一个或多个后端上运作 这些包含Apple的 高层次机器学习框架 Core ML和Create ML 以及专门的框架 像是视觉和自然语言 BNNS提供支持 广泛层次类型的训练和推论 以及支持显示在下面的优化器 在这次的释出内容 我们增加支持几个新的层次类型 嵌入、随机填充和量化 同时支持AdamW优化器 我们也改善了现有的层次 加入两个新的激活功能 SiLU和HardSwish 以及支持新的算数功能 三进位选择、乘积累加 以及元素积的最小值和最大值 层间融合能够 立刻消耗一层的输出 使它成为下一层的输入 避免把它写到内存上 然后再把它重新读取进来 我们在卷积和全连接层 与新的量化层之间加入层间融合 还有在算数和标准化层之间 加入融合 其他改良包含改善支持 优化器中的梯度裁剪 这也能被当成独立运行的功能 以及针对Adam架构的优化器的 AMSGrad支持 这些改良进一步扩展了 我们能够加速的范围和网络结构 现在让我跟大家介绍simd.h上的改良 simd.h提供符合CPU的缓存器的 小向量和矩阵计算原语 包含支持诸如正弦和余弦函数 以及实用的几何运算 包含支持四元数 在simd.h中最合我意的是 我们只要使用10分的努力 就能取得90分向量化的效益 让我示范给你们看 这是我刚刚建立的 神经网络激活函数 大家可以看到 它有三个不同的分支 如果输入小于负值pi 那我会回传0 如果是介于负值pi和pi之间 我会回传2乘以X的指数 再乘以X加pi除以2的值 反之 如果它的值大于pi 我会回传2乘以X的指数 很好 不过要是我有很大量的数据 我可能会希望它运算得 比纯量循环允许的速度更快 让我示范如何在simd中实作这部分 这里我已经放入一些样板 一个可以让我轻松地将向量 写入缓冲的延伸 和一个会在我们的输出数组 重复的循环 以一个长度为增量 每次八个向量 有趣的部分是如何将我们的纯量函数 转译成simd当量 让我们再从我们的纯量编码开始 我看到它有几个分支 这些都不适合用于向量化 让我们用能根据遮罩合并的部分 来建构它 更仔细来看 如果X小于负值pi 我会回传0 如果是大于 我会回传涉及2乘以X的指数的表达式 让我们把它拉出来 现在 我们要用那个Y建构一个向量 以0取代在X为元素积 小于负值pi的位置 接下来 我们可以来看大于的例子 这里 我们会在高区域乘以1 或是在中间区域乘以X加pi除以2的值 让我们用同样的方式写入那个 我们拿X加pi除以2的表达式 这次我们要以1取代 X为元素积大于或等于pi的位置 现在 我们只需要 将这两个数量相乘 很显然 如果以一个0元素乘以B的值 还是会回传0 让我们执行它 看看会长什么样子
现在 我可以从下面的控制台看到 我的新simd版本比之前的纯量编码 几乎快了三倍 在这次的释出中 simd有什么改良? 我们改善了C++程序员 使用模版时的可用性 我们加入了类型和特征结构 让大家不用复杂的编码结构 也不需要自己实作类似的类型 就可以在底层纯量类型和向量长度 以及具体simd类型之间移动 为了简化它们的使用 我们还加入便利的别名 来减少对C++样板的需求 这个范例它们在使用中的样子 向量和矩阵类型让我们可以 从底层类型 例如浮点数或整数 和向量长度到具体类型 还有成员能提供相关类型的存取 例如未对齐版本 和从比较得到的遮罩类型 Vector_t和Matrix_t别名 提供简化的语法来存取和我们之前 一样的目的地 get_traits结构让我们可以 进到其他方向 从具体simd类型移动到通用类型 另外也有在一般使用案例中 可以用来简化语法的别名 我们也加入了 制作和转换函数的模板版本 让它们可以在模板编码中使用 这些和现有函数的功能相同 但是现在它们的目的地类型 是模板参数 而不是函数名称的一部分 除了C++的改良 我们还新增了几项 能支持我们所有语言的函数 这些是分类函数 例如isfinite和isinf 这会在libm中提供 纯量函数的向量版本 和用来计算伽玛函数的新函数 以及simd矩阵的迹 现在 我们来介绍Apple文档库 和我们新的Apple加密文件格式 Apple文档库在这十年大部分的时间中 一直在强化我们的系统更新 在macOS 11的释出中 我们提供大家压缩容器 和文件格式 在macOS 12的新内容 我们在这项支持新增了加密的API 文件格式本身 提供最新的、模块化的方式 让你可以选择你想要储存为 哪一种文件属性和元数据 它是可串流的 也就是说你不用担心 要一次把所有数据放到内存上 它也支持独立的清单文件 编列索引为大型文档 像是文件系统图像 新的Apple加密文档是建立在这上面 将压缩、经认证的加密和数字签名 结合成单一的安全包裹 它带给大家由我们的安全团队 和外面的专家所设计和审查的 最先进的密码技术 数据保密代表你的数据会保持机密 数据验证代表你可以确保 数据在输送过程中没有损坏 发件人验证代表你会知道是谁寄出的 签章隐私代表在公钥环境中 只有你和发件人知道是谁签署的 我们还让元数据模糊 像是文档长度 并且加入重新签章的攻击防护 有了上面这些 代表你可以很肯定 你的数据是隐私和安全的 为了有利于正确的部署 我们提供几种不同的配置文件 给不同的使用案例 基本的配置文件是没有加密的 数字签名 这可以用在像是软件更新 这种内容不需要保密 但是你希望确保数据没有被篡改 接着 我们有对称式加密 有没有签章都可以 使用安全的共享二元密钥 这和下一个选项类似 下一个是用密码而不是二元密钥 最后 我们有成熟的公钥加密 一样有没有签章都可以 在配置文件中 压缩是选择性的 而数据则都必须是经验证的 要使用这些格式 我们提供了几种命令行工具 要使用压缩文件案这部分的格式 我们有compression_tool 要使用加密的文档 则有aea aea工具可以处理整个容器 当然也有由AppleArchive框架提供 在Swift和C使用的API 它是基于串流的 同时允许连续和随机存取 它是以多线程来实作 因此有非常快速的性能 让我们来看看这个API执行时的样子 这里 我们弄了一个简单的示范app 窗口的上半部做为 我们想要加密的内容的 拖曳目标 而下半部是简单的状态区块 假设我想要加密这个TopSecret目录 我把它拖放到这个app中 喔不!出现一个错误 我们还没实作这个功能! 让我们现在来做吧 我们要做什么才能用Apple文档库 来加密它? 首先 我们需要一个加密环境 它会描述要使用的算法和配置文件 以及我们加密的内容 我们还需要一个文档串流 那是我们会把文档写入的地方 我们把这些结合在一起 来建立加密串流 加密串流会加密位的串流 所以我们需要一个能把 我们想加密的目录 转译成那种串流的转接器 这就是编码器串流 当然 数据是从相反方向 流向对象建立 我们把文档入口送进编码器串流 编码器串流会把这些转换成字节 来做加密串流 之后加密串流会将数据 加密到文件串流上 让我们来看看它在编码中的样子 这里 我们指定要用对称式配置文件 而这个“没有”代表 我们没有要用数字签名 枚举的开头这部分 只是在指定我们想要使用的算法 这里 我们要用“lzfse” 来压缩数据 当环境建立好了 我们只需要指定我们的 对称式加密密钥 接着 我们要建立那三个串流 首先 我们建立文件串流 然后我们把它和环境结合 来建立encryptionStream 最后 我们得到encoderStream 很重要的是我们要记得 以正确的顺序来关闭这些串流 特别是关闭encryptionStream 会在后台处理很多工作 因为它会签署和封印文档 最后 我们只需要 将文件送进encoderStream 我要指定我想要编码的文档属性 然后调用 writeDirectoryContents方法 剩下的就是将 带有加密密钥的状态信息 打印到控制台 让我们来看看有没有成功 当我把我们的TopSecret目录 拖到app中 它成功了 目录被加密 并且打印出我们的加密密钥 现在 当我把我们加密的文档 拖放到app中 它试着解密这个文档 并且请求加密密钥 让我们复制贴上那个加密密钥 看看里面是什么内容 嗯 真可口! 这就是我要介绍Apple加密文档的 全部内容 让我们来整理一下 今天我跟大家介绍了 加速框架的改良 包含支持在BNNS中的新层次类型 以及扩展的C++支持 和在simd.h中的其他功能 接着我跟大家介绍Apple文档库库 和新的Apple加密文件格式 以及它们在框架中的支持 谢谢 希望你们喜欢接下来的WWDC ♪
-
-
1:55 - Using Accelerate in C/C++
// How to use in your own code // C / Objective C / C++ #include <Accelerate/Accelerate.h> // Add framework Accelerate #include <AppleArchive/AppleArchive.h> // Add framework AppleArchive #include <Compression/Compression.h> // Add framework Compression #include <simd/simd.h> // No framework to add // Swift import Accelerate import AppleArchive import Compression import simd
-
4:26 - simd example
import simd public func swishharder_scalar (_ data: [Float]) -> [Float] { return data.map { x in if x <= -.pi { return 0 } // { 0 if x ≤ -π if x <= .pi { return 2*exp(x) * (x + .pi)/2 } // f(x) = { 2eˣ * (x+π)/2 if -π < x < π else { return 2*exp(x) } // { 2eˣ if π ≤ x } } func swishharder_elementwise(_ x: SIMD8<Float>) -> SIMD8<Float> { let y = 2*simd.exp(x) let a = y.replacing(with: 0, where: x .<= -.pi) let b = ((x + .pi)/2).replacing(with: 1, where: .pi .<= x) return a*b } extension SIMD { internal func store( into buffer: UnsafeMutableBufferPointer<Scalar>, startingAt offset: Int ) { for i in 0 ..< scalarCount { buffer[offset + i] = self[i] } } } public func swishharder_simd(_ data: [Float]) -> [Float] { return Array<Float>(unsafeUninitializedCapacity: data.count) { (buffer: inout UnsafeMutableBufferPointer<Float>, count: inout Int) in for i in stride(from: 0, to: data.count, by: 8) { let v = SIMD8(data[i ..< i+8]) let w = swishharder_elementwise(v) w.store(into: buffer, startingAt: i) } count = data.count } }
-
12:14 - AEA Encryption
/// Encrypts and archives the directory at the specified URL. /// /// - Parameter sourceURL: The URL of the directory that the function encrypts and archives. /// - Returns: A string containing the status message. /// /// This function writes the result to `directory`. The archive shares the name /// of the supplied directory with an `aea` extension. static func encrypt(sourceURL: URL) -> ConsoleMessage { // Verify that the URL path represents a directory. if !sourceURL.hasDirectoryPath { return ConsoleMessage(status: .error, message: "The specified URL doesn't point to a directory.") } guard let source = FilePath(sourceURL) else { return ConsoleMessage(status: .error, message: "Unable to create file path from source URL.") } // Create the destination `FilePath`. let destination = directory .appending(sourceURL.lastPathComponent) .appending(".aea") let archiveDestination = FilePath(destination) // Create the encryption context + setup credentials let encryptionKey = SymmetricKey(size: .bits256) let context = ArchiveEncryptionContext( profile: .hkdf_sha256_aesctr_hmac__symmetric__none, compressionAlgorithm: .lzfse) do { try context.setSymmetricKey(encryptionKey) } catch { return ConsoleMessage(status: .error, message: "Error setting password (\(error).)") } // Create the file stream, encryption stream, archive encode stream. guard let archiveDestinationFileStream = ArchiveByteStream.fileStream( path: archiveDestination, mode: .writeOnly, options: [ .create, .truncate ], permissions: FilePermissions(rawValue: 0o644)), let encryptionStream = ArchiveByteStream.encryptionStream( writingTo: archiveDestinationFileStream, encryptionContext: context), let encoderStream = ArchiveStream.encodeStream( writingTo: encryptionStream) else { return ConsoleMessage(status: .error, message: "Error creating streams.") } // Remember to close things in the correct order defer { try? encoderStream.close() try? encryptionStream.close() try? archiveDestinationFileStream.close() } // Encode all files in the target directory with the specifed fields. do { let fields = ArchiveHeader.FieldKeySet("TYP,PAT,DAT,UID,GID,MOD")! try encoderStream.writeDirectoryContents(archiveFrom: source, keySet: fields) } catch { return ConsoleMessage(status: .error, message: "Error writing directory contents.") } if let url = URL(archiveDestination) { NSWorkspace.shared.activateFileViewerSelecting([url]) } let message = """ Encrypted with key '\(encryptionKey.base64Encoded)'. Archived and encrypted to: \(archiveDestination.description). """ return ConsoleMessage(status: .encryptionSuccess(base64EncodedKeyData: encryptionKey.base64Encoded), message: message) }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。