【问题标题】:How many layers are between my program and the hardware?我的程序和硬件之间有多少层?
【发布时间】:2010-04-14 21:09:54
【问题描述】:

不知何故,我感觉现代系统,包括运行时库、异常处理程序和内置调试器,在我的 (C++) 程序和 CPU/硬件的其余部分之间构建了越来越多的层。

我在想这样的事情:

1 + 2 >> 操作系统顶层 >> 运行时库/帮助程序/错误处理程序 >> 大量的 DLL 模块 >> 操作系统内核层 >> 你真的要运行 1 + 2 吗?-Windows 弹出窗口(不要不要认真)>>操作系统内核层>>硬件抽象>>硬件>>经过至少100英里的电路>>最终到达CPU>>添加1、2>>一直回到我的程序

几乎所有技术上的东西都是错误的,而且顺序是随机的,但你明白我的意思吗?

  • 当我在 Windows 上运行一个在运行时计算 1 + 2 的 C++ 程序时,这条链长/短多少?

  • 如果我在口译员中这样做呢? (Python|Ruby|PHP)

  • 这条链条在现实中真的如此戏剧化吗? Windows 真的尝试“不挡道”吗?例如:直接连接我的二进制硬件?

【问题讨论】:

  • 强制性 XKCD 参考:xkcd.com/676
  • 我不知道那个,符合问题:D

标签: performance hardware abstraction


【解决方案1】:

C++ 中的“1 + 2”被直接翻译成直接在 CPU 上执行的 add 汇编指令。您所指的所有“层”实际上只有在您开始调用库函数时才会发挥作用。例如一个简单的printf("Hello World\n"); 会经过多个层(以 Windows 为例,不同的操作系统会有所不同):

  1. CRT - C 运行时实现 %d 替换并创建单个字符串,然后在 kernel32 中调用 WriteFile
  2. kernel32.dll 实现WriteFile,注意到句柄是一个控制台并将调用定向到控制台系统
  3. 字符串被发送到实际托管控制台窗口的 conhost.exe 进程(在 Windows 7 上,csrss.exe 在早期版本上)
  4. conhost.exe 将字符串添加到表示控制台窗口内容的内部缓冲区并使控制台窗口无效
  5. 窗口管理器注意到控制台窗口现在无效并向其发送 WM_PAINT 消息
  6. 为了响应 WM_PAINT,控制台窗口(仍在 conhost.exe 内)在 GDI32.dll(或者可能是 GDI+?)内进行一系列 DrawString 调用
  7. DrawString 方法循环遍历字符串中的每个字符,并且:
    1. 在字体文件中查找字形定义以获得字形的轮廓
    2. 在缓存中检查该字形以当前字体大小呈现的版本
    3. 如果字形不在缓存中,它会以当前字体大小栅格化轮廓并缓存结果以供以后使用
    4. 将像素从光栅化字形逐个像素复制到您指定的图形缓冲区中
  8. 所有DrawString 调用完成后,窗口的最终图像将发送到 DWM,并在此加载到图形卡的图形内存中,并替换旧窗口
  9. 绘制下一帧时,显卡现在使用新图像来渲染控制台窗口,并且您的新字符串就在那里

现在我已经简化了很多层(例如,显卡渲染内容的方式是一个完整的“另一层抽象”)。我可能犯了一些错误(很明显,我不知道 Windows 的内部实现方式),但希望它能给你一个想法。

不过,重要的一点是,沿途的每一步都为系统增加了某种价值。

【讨论】:

  • ++ 这是一个很好的解释。我要补充一点,IDE 调试器不会消耗任何性能(除非您添加数据中断)。此外,解释语言通常比编译语言慢 1-2 个数量级。根据应用程序,这可能是也可能不是问题。
【解决方案2】:

正如 codeka 所说,当您调用库函数时会发生很多事情,但您需要记住的是打印字符串或显示 jpeg 或其他任何非常复杂的任务。当所使用的方法必须在每种情况下对每个人都有效时,更是如此;数百个边缘案例。

这真正意味着当您编写严肃的数字运算、国际象棋、天气预报代码时,不要调用库函数。而是只使用可以并且将由 CPU 直接执行的廉价函数。此外,计划昂贵的功能在哪里可以产生巨大的影响(在最后打印所有内容,而不是每次都通过循环)。

【讨论】:

    【解决方案3】:

    无论有多少抽象级别,只要努力工作以最有效的方式完成即可。

    在一般意义上,您会“模仿”您的最低级别,例如您会在运行一些执行不佳的应用程序的 x86 CPU 上模拟 68K CPU,但它的性能不会比原始硬件差。否则你一开始就不会模仿它。例如。今天,大多数用户界面逻辑都是使用高级动态脚本语言实现的,因为它更高效,而核心内容由优化的低级代码处理。

    在性能方面,总是首先遇到困难。介于两者之间的事情永远不会受到性能问题的影响。例如。每秒处理 2-3 次按键的按键处理程序可以在编写糟糕的代码上花费大量资金,而不会影响最终用户体验,而 mpeg 编码器中的运动估计器将完全失败,因为仅在软件中实现而不是使用专用硬件。

    【讨论】:

      猜你喜欢
      • 2012-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-07
      • 2012-11-14
      • 2012-02-23
      • 2016-12-17
      • 2013-09-10
      相关资源
      最近更新 更多