这个基于 NOP 的 sleep()/delay() 函数使用了太多的 CPU 功率 (20%!) -- 如何解决?[复制]

This NOP-based sleep()/delay() function uses way too much CPU power (20%!) -- how to fix? [duplicate]

提问人:greg spears 提问时间:11/6/2023 最后编辑:Peter Cordesgreg spears 更新时间:11/6/2023 访问量:164

问:

我正在尝试构建一个跨平台的sleep()/delay()。下面的代码工作得很好,除了 - 与GCC或Microsoft sleep() - 不同 - 它不会将其CPU周期返回给操作系统。编译器原生 sleeps() 的好处是,您可以像我们的示例一样在循环中运行它们,并且 CPU 使用率接近于零。在此 delay() 代码中并非如此。它平均消耗高达 20%(!) 的 CPU。如果我将 #if defs 更改为调用 Sleep(),CPU 使用率将接近 0%。

“嗯,很明显,你的内联程序集显然是从最终的可执行文件中优化出来的,显然。”

这就是我的想法——这就是为什么我用现在注释掉的 ASM 代码进行测试,它增加了一个重要的循环。

我增加了循环数,直到它严重影响了延迟。也就是说,由于所有这些对 NOP 的调用,延迟时间比请求的 2 毫秒要长得多。因此,证据行为表明汇编代码在很大程度上是最终可执行文件的一部分。(它没有优化出来)。

我真的很惊讶 NOP 没有将 CPU 释放回操作系统!

那么,我们如何才能以一种 delay() 确实将其 CPU 周期返回给操作系统的方式进行编码,就像原生 sleep() 一样

所需的平台是 WIN32 和 LINUX(稍后)。如果有人足够聪明,可以同时编写两者,那就太好了。但是,如果您只能回答一个问题,那么 WIN32 是现在/今天/这个问题的可接受答案,请并谢谢。

这是我尝试过的代码。我没想到会有如此强烈的 CPU 消耗。但是,不管NOP的大量使用--以及NOP的创造性实现--这就是我得到的。

#include <stdio.h>
#include <time.h>


void delay(int num)
{
clock_t start = clock();

    while((clock() - start) < num )
    {
#if 1
        _asm{
            //mov ECX,100000000
            //lab5:
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            //loop lab5
        };
#else
        Sleep(1);
#endif
    }
}

int main()
{
unsigned iii=1000;  

    while(iii--)
    {
        printf("Count: %d        \r",iii);
        delay(2);
    }
    return 0;
}
C 装配 延迟 空操作 忙等待

评论

2赞 Peter Cordes 11/6/2023
nop不是系统调用。CPU 必须获取并解码它才能看到接下来会发生什么。即使 x86 也不是系统调用,因此操作系统无法控制 CPU 以使其运行其他内容。pause
8赞 Eric Postpischil 11/6/2023
如果您的进程正在执行指令,则它正在使用处理器。NOP 指令不会改变这一基本事实。若要停止使用处理器,请通过执行适当的系统调用来告诉操作系统您不想再使用处理器(暂时)。操作系统负责处理器。你的过程不是。
3赞 Peter Cordes 11/6/2023
@ecm:确实是完全特权 (felixcloutier.com/x86/hlt),即使 IOPL=0,也无法从 OP 目标平台(Windows 和 Linux)上的用户空间使用。如果它可用,操作系统任务记帐可能会将其计为使用 CPU 时间的进程,因为假设就像一个 long 或 /,不会将控制权交还给操作系统,以便在任何任务等待 CPU 时间时运行另一个任务。Linux / POSIX 具有 、 和 。Windows 大概类似于 。hlthlttpauseumonitorumwaitsched_yield()sleepnanosleepSleep(0)sched_yield
7赞 Eric Postpischil 11/6/2023
回复“在链接中,我没有看到我在这个问题中要求的非处理器密集型代码解决方案 - 我错过了什么?”:用户说明中没有解决方案。用户进程不控制处理器。操作系统控制处理器。若要停止使用处理器,请进行系统调用。
3赞 Peter Cordes 11/6/2023
格雷格,@0____的评论是讽刺,没有帮助。

答: 暂无答案