图灵程序设计丛书:多核应用编程实战
第1章 硬件、进程和线程1.1 计算机的内部结构1.2 多核处理器的缘起1.2.1 在单芯片上支持多线程1.2.2 通过处理器核心流水线作业提高指令发出率1.2.3 使用缓存保存最近使用的数据1.2.4 用虚拟内存存储数据1.2.5 从虚拟地址转换到物理地址1.3 多处理器系统的特征1.4 源代码到汇编语言的转换1.4.1 32位与64位代码的性能1.4.2 确保内存操作的正确顺序1.4.3 进程和线程的差异1.5 小结第2章 高性能编码2.1 定义性能2.2 了解算法复杂度2.2.1 算法复杂度的示例2.2.2 算法复杂度的重要性2.2.3 谨慎运用算法复杂度2.3 结构如何影响性能2.3.1 在源代码和生成结构上权衡性能和便利性2.3.2 利用库结构化应用程序2.3.3 数据结构对性能的影响2.4 编译器的作用2.4.1 两种编译器优化2.4.2 选择合适的编译器选项2.4.3 如何用跨文件优化提高性能2.4.4 使用配置文件反馈2.4.5 潜在的指针别名会如何抑制编译器优化2.5 通过分析确定占用时间的地方2.6 怎样避免手动优化2.7 从设计角度看性能2.8 小结第3章 识别并行机会3.1 使用多进程提高系统工作效率3.2 多用户使用一个系统3.3 通过整合提高机器工作效率3.3.1 用容器隔离共享一个系统的应用程序3.3.2 使用虚拟机监控程序托管多个操作系统3.4 采用并行机制提高单个任务的性能3.4.1 理解并行应用程序3.4.2 并行如何影响算法的选择3.4.3 Amdahl定律3.4.4 确定最大实际线程数3.4.5 同步成本怎样降低扩展性3.5 并行模式3.5.1 使用SIMD指令的数据并行3.5.2 通过进程或线程实现并行化3.5.3 多个独立任务3.5.4 多个松散耦合的任务3.5.5 相同任务的多个副本3.5.6 单个任务拆分到多个线程3.5.7 使用流水线任务完成某个事项3.5.8 将工作分配给客户端和服务器3.5.9 将责任划分给生产者和消费者3.5.10 结合多种并行化策略3.6 依赖关系对并行运行代码能力的影响3.6.1 反依赖和输出依赖3.6.2 通过推测打破依赖3.6.3 关键路径3.7 发现并行机会3.8 小结第4章 同步和数据共享4.1 数据争用4.1.1 使用工具检测数据争用4.1.2 避免数据争用4.2 同步原语4.2.1 互斥量和临界区4.2.2 自旋锁4.2.3 信号量4.2.4 读写锁4.2.5 屏障4.2.6 原子操作和无锁代码4.3 死锁和活锁4.4 线程和进程间的通信4.4.1 内存、共享内存和内存映射文件4.4.2 条件变量4.4.3 信号和事件4.4.4 消息队列4.4.5 命名管道4.4.6 通过网络栈进行通信4.4.7 线程之间共享数据的其他方法4.5 存储线程私有数据4.6 小结第5章 使用POSIX线程5.1 创建线程5.1.1 线程终止5.1.2 用子线程接收和传递数据5.1.3 分离线程5.1.4 设置pthread的属性5.2 编译多线程代码5.3 进程终止5.4 线程之间共享数据5.4.1 使用互斥锁保护访问5.4.2 互斥锁属性5.4.3 使用自旋锁5.4.4 读写锁5.4.5 屏障5.4.6 信号量5.4.7 条件变量5.5 变量和内存5.6 多进程编程5.6.1 在进程之间共享内存5.6.2 在进程之间共享信号量5.6.3 消息队列5.6.4 管道和命名管道5.6.5 使用信号与进程通信5.7 套接字5.8 可重入代码和编译器标志5.9 小结第6章 Windows线程6.1 创建Windows本机线程6.1.1 终止线程6.1.2 创建和重新启动挂起的线程6.1.3 使用内核资源的句柄6.2 同步和资源共享的方式6.2.1 线程间需要同步的一个例子6.2.2 保护对临界区代码的访问6.2.3 用互斥量保护代码段6.2.4 轻量级读写锁6.2.5 信号量6.2.6 条件变量6.2.7 向其他线程或进程发出事件完成的信号6.3 Windows中的宽字符串处理6.4 创建进程6.4.1 在进程之间共享内存6.4.2 在子进程中继承句柄6.4.3 互斥量命名及其在进程间的共享6.4.4 用管道通信6.4.5 用套接字进行通信6.5 变量的原子更新6.6 分配线程本地存储6.7 设置线程的优先级6.8 小结第7章 自动并行化和OpenMP7.1 使用自动并行化产生并行代码7.1.1 识别和并行约简7.1.2 对包含调用的代码进行自动并行化7.1.3 协助编译器实现代码的自动并行化7.2 使用OpenMP生成并行应用程序7.2.1 使用OpenMP并行化循环7.2.2 OpenMP应用程序的运行时行为7.2.3 OpenMP并行区域中的变量作用域7.2.4 使用OpenMP并行化约简7.2.5 在并行区域外访问私有数据7.2.6 使用调度改进工作分配7.2.7 用并行段完成独立工作7.2.8 嵌套并行7.2.9 使用OpenMP动态定义并行任务7.2.10 保持数据对线程私有7.2.11 控制OpenMP运行时环境7.2.12 等待工作完成7.2.13 限制执行代码区域的线程7.3 确保并行区域的代码按顺序执行7.4 折叠循环改进工作负荷均衡7.5 强制实现内存一致性7.6 并行化示例7.7 小结第8章 手工编码的同步和共享8.1 原子操作8.1.1 用比较和交换指令构成更复杂的原子操作8.1.2 强制实现内存排序以确保正确操作8.1.3 编译器对内存排序指令的支持8.1.4 编译器对操作的重新排序8.1.5 易失变量8.2 操作系统提供的原子操作8.3 无锁算法8.3.1 Dekker算法8.3.2 带循环缓存的生产者/消费者8.3.3 扩展到多个消费者或生产者8.3.4 将生产者/消费者扩展到多个线程8.3.5 更改生产者/消费者代码为使用原子操作8.3.6 ABA问题8.4 小结第9章 基于多核处理器的扩展9.1 对应用程序扩展的限制9.1.1 串行代码对性能的限制9.1.2 超线性扩展9.1.3 工作负荷不均衡9.1.4 热锁9.1.5 库代码扩展9.1.6 工作量不足9.1.7 算法限制9.2 扩展的硬件限制9.2.1 核心之间的带宽共享9.2.2 伪共享9.2.3 缓存冲突和容量9.2.4 流水线资源匮乏9.3 操作系统对扩展性的限制9.3.1 过度订阅9.3.2 使用处理器绑定改善内存局部性9.3.3 优先级反转9.4 多核处理器和扩展9.5 小结第10章 其他并行技术10.1 基于GPU的运算10.2 语言扩展10.2.1 线程构建模块10.2.2 Cilk++10.2.3 GrandCentralDispatch10.2.4 为未来C和C++标准提议的可能功能10.2.5 微软的C++/CLI10.3 其他语言10.4 集群技术10.4.1 MPI10.4.2 以MapReduce作为扩展策略10.4.3 网格10.5 事务性内存10.6 向量化10.7 小结第11章 结束语11.1 编写并行应用程序11.1.1 识别任务11.1.2 估算性能提升11.1.3 确定依赖关系11.1.4 数据争用和互斥锁扩展限制11.1.5 锁的粒度11.2 多核处理器上的并行代码11.3 并行化的未来参考文献索引
Darryl Gove,Oracle Solaris Studio编译团队的高级首席软件工程师,主要负责应用程序和基准方面的分析、并行和优化。他具有英国南安普顿大学运筹学硕士和博士学位,另著有Solaris Application Programming、The Developer’s Edge。此外,他经常在个人博客上发表关于性能、优化、多线程和编码的文章。
《图灵程序设计丛书:多核应用编程实战》是一本全面实用的多核应用编程指南,旨在介绍如何编写功能正确、性能优越且适合扩展为在多个CPU核心的系统运行的应用程序。《图灵程序设计丛书:多核应用编程实战》面向多种操作系统和处理器类型引用程序示例,内容涵盖类UNIX操作系统(Linux、OracleSolaris、OSX)和Windows系统上多核应用的编写方法、多核的硬件实现对应用程序的性能影响、编写并行应用程序时要避免的潜在问题,以及如何编写可扩展至大量并行线程的应用程序。
比价列表