借助C++进行Windows开发:探索高性能算法

在并发空间中,诸如协调、异步行为、响应性和可伸缩性等问题会成为关注的焦点。这些都是开发人员在设计应用程序时必须考虑的一些比较深奥的主题。但是,也许是由于缺乏经验或缺乏合适的性能工具,一些同样重要的主题却常常被忽略。高性能算法就是其中一例。

在企业级别,开发人员会仔细斟酌分布式文件系统和缓存、群集、消息队列和数据库等问题。但是如果最核心的算法和数据结构效率低下,考虑这些又有什么用呢?

算法效率并不像您认为的那样简单。单处理器上设计良好的算法通常可以胜过多处理器上的低效实现。但是现在,当多处理器已经可用时,设计良好的算法还要显示出可衡量的可伸缩性和效率。由于会使问题变得更为复杂,因此针对单处理器进行优化的算法通常很难并行执行,而效率略低的算法通常可以在多处理器环境中发挥更好的性能。

为了说明这一点,我将使用 Visual C++ 展示一个非常简单的算法的开发过程,但实际上它不简单,即使乍看起来像是如此。下面是我们需要实现的一些内容:

void MakeGrayscale(BYTE* bitmap,
          const int width,
          const int height,
          const int stride);

位图参数,指向一幅 32 位/像素的图像。再次重申,这是本文的重点。跨距的绝对值,指示内存中一行像素到下一行像素的字节数。每行的末尾可能存在填充内容。跨距的符号,指示这些行在内存中是自上而下(正跨距)还是自下而上(负跨距)。

让我们首先确定着手点。我们可以使用下面的结构来表示内存中的像素:

typedef unsigned char BYTE; // from windef.h
struct Pixel
{
  BYTE Blue;
  BYTE Green;
  BYTE Red;
  BYTE Alpha;
};

通过快速的 Web 搜索,我们确定对于一个给定颜色的像素可通过混合 30% 的红色、59% 的绿色和 11% 的蓝色来获得合理的灰度值。下面是将一个像素转换为灰度级的简单函数:

void MakeGrayscale(Pixel& pixel)
{
  const BYTE scale = static_cast<BYTE>(0.30 * pixel.Red +
                     0.59 * pixel.Green +
                     0.11 * pixel.Blue);
  pixel.Red = scale;
  pixel.Green = scale;
  pixel.Blue = scale;
}

要计算位图内某个特定像素的字节偏移,可计算其水平位置与像素大小的乘积以及其垂直位置与跨距的乘积,然后将这些值相加:

offset = x * sizeof(Pixel) + y * stride

那么,该如何实现 MakeGrayscale 函数呢?如果您跳过这部分而不做其他考虑,您可能会写出类似于图 1 所示的算法行。乍一看这似乎是合理的,采用这样的方法,似乎可以很好地对小位图进行处理。但对于较大的位图会怎样呢?对 20,000 * 20,000 像素的位图又会如何?

图 1 低效的单线程算法

void MakeGrayscale(BYTE* bitmap,
          const int width,
          const int height,
          const int stride)
{
  for (int x = 0; x < width; ++x)
  for (int y = 0; y < height; ++y)
  {
    const int offset = x * sizeof(Pixel) + y * stride;
    Pixel& pixel = *reinterpret_cast<Pixel*>(bitmap + offset);
    MakeGrayscale(pixel);
  }
}

我恰好有一个配有四核 Intel Xeon X3210 处理器的 Dell PowerEdge。这种机器的时钟速度为 2.13GHz,前端总线为 1066MHz,二级缓存为 8MB,此外还具有其他各种超炫的功能。不可否认,它并不是最新的 Intel Xeon 处理器,但它确实值得称道。它由 64 位版本的 Windows Server 2008 驱动,非常适合做性能测试。

有了这些支持,我对宽度为 20,000 像素且高度也为 20,000 像素的位图运行了图 1 所示的算法。平均来说,它在 46 秒钟内进行了 10 余次迭代。不可否认,这张位图相当大,约占 1.5GB 的空间。但是这真的是问题所在吗?我的服务器有 4GB 内存,因此不需要分页磁盘。但图 2 显示了大家都非常熟悉的处理器使用率视图。


图 2 低效单线程算法的处理器使用率

时间: 2024-08-03 18:55:26

借助C++进行Windows开发:探索高性能算法的相关文章

借助C++进行Windows开发:Windows Template Library 8.0

目录 任务对话框 Aero 向导 新的文件对话框 有待探索的其他 WTL 功能 负责 Windows Template Library (WTL) 的开发人员最近发布了最新版本,这个模板库非常优秀,完全支持随 Windows Vista 引入的几乎所有新用户界面功能和增强功能.本月,我将重点介绍此最新版本中的一些新功能.如果您尚不熟悉 WTL 以及它与 Visual C++ 开发领域之间的适应情况,我在开头将简单地加以介绍. 为了能够轻松创建 COM 客户端和服务器,同时尽可能生成最小.最快的代

借助 C++ 进行 Windows 开发:Windows 运行时应用程序模型

我们的生活充满了抽象.作为开发人员,如果我们不了解抽象的定义就去使用它,则通常会让我们 陷入困境.抽象有时是零散的,且无法完全隐藏基本复杂性.别误解我的意思,其实抽象是很有用的. 它们能为用户和开发人员提供帮助,而如果您深入研究您通常依赖的抽象来了解其运作方式,则会让您 受益匪浅.此外,承认这一现实的库通常比不承认这一现实的库更为成功,部分是因为前者允许您在必 要时绕过抽象. Windows 运行时 (WinRT) 就是一个这样的抽象,在本月的专栏中,我将通过研究 WinRT 核心应用 程序模型

借助C++进行Windows开发:Windows服务增强

目录 延迟自动启动服务 改进关机可预见性 失败操作和受控停止 减少权限 保护服务数据 用受限令牌保护其他项目 接收服务通知 后续内容 Windows服务开发的状态自从在 Windows NT 中出现服务以来一直没有较大的改变,但是 Windows Vista 和 Windows Server 2008 打破了这一僵局.这其中的许多功能主要是为了以更简捷的方式生成更安全的服务,但是在与安全性不相关的服务功能中,有些功能是为了提高 Windows 的整体响应能力和可靠性. 延迟自动启动服务 可通过

借助C++进行Windows开发:Windows Imaging Component基础知识

目录 入门 解码图像 编码图像 WIC 图像工厂 使用流 通过 WPF 使用 WIC 下一步是什么? Microsoft Windows Imaging Component (WIC) 是用于编码.解码和操控图像的可扩展框架.WIC 最初是为 Windows Vista 和 Windows Presentation Foundation (WPF) 而设计的,但现在,不仅 Windows Vista 和 Microsoft .NET Framework 3.0 及更高版本附带此框架,而且它还是

借助 C++ 进行 Windows 开发:使用 DirectWrite 和最新 C++ 管理字体

DirectWrite 是一种相当强大的文本布局 API. 它支持从 XAML 和 Office 2013 的 Windows 运行 时 (WinRT) 实现到 Internet Explorer 11 和更高版本的几乎所有领先 Windows 应用程序和技术. 它 本身并不是呈现引擎,但与 Direct2D 有很近的关系,是 Direct2D 在 DirectX 系列中的同级产品. 当然,Direct2D 是首要的硬件加速即时模式图形 API. 您可以将 DirectWrite 与 Direc

借助 C++ 进行 Windows 开发:Windows 运行时的呈现

我的上一个专栏中讨论了 Windows 运行时 (WinRT) 应用程序模型 (msdn.microsoft.com/magazine/dn342867). 我演示了如何通过标准 C++ 和经典 COM 来编写 Windows 应用商店或 Windows Phone 应用程序,其中仅使用了一些 WinRT API 函数. 毫无疑问,您 不必使用 C++/CX 或 C# 这样的语言投射. 能够绕过这些抽象概念是一种强大的功能,同时也是一种 了解这项技术工作方式的很好的方法. 我在 2013 年 5

微软的树莓派?Windows开发板Sharks Cove的意义

    Build 2014开发者大会上,微软介绍了代号 Sharks Cove(鲨鱼湾)的 Windows 开发板,采用Intel Atom Z3735G处理器,配备1GB内存和16GB的存储容量.日前,Sharks Cove开发板开始接受预定,售价299美元,其中包含了一份Windows 8.1操作系统镜像文件. Sharks Cove 开发板由英特尔操刀设计,可以帮助硬件工程师更轻松地开发和验证 Windows 驱动程序,主要用来支持Windows 独立硬件供应商(IHV)和原始设计制造商

Android艺术开发探索——第二章:IPC机制(下)

Android艺术开发探索--第二章:IPC机制(下) 我们继续来讲IPC机制,在本篇中你将会学习到 ContentProvider Socket Binder连接池 一.使用ContentProvider ContentProvider是Android中提供的专门用来不同应用之间数据共享的方式,从这一点来看,他天生就是适合进程间通信,和Messenger一样,ContentProvider的底层实现同样也是Binder,由此可见,Binder在Android系统中是何等的重要,虽然Conten

api-AE + c# 开发 pTopologicalOper.Difference算法 API报错

问题描述 AE + c# 开发 pTopologicalOper.Difference算法 API报错 //原始线图层 IFeatureClass pFeatureClass = pLayer.FeatureClass; //获取要素 IFeature pFirstFeature = pFeatureClass.GetFeature(85); IFeature pSecondFeature = pFeatureClass.GetFeature(420); //获取Geomtry并统一投影坐标系