为什么我的程序设计为用完 RAM 和 CPU 不使用所有 RAM 和 CPU?

  • 本文关键字:CPU RAM 程序设计 c++ windows
  • 更新时间 :
  • 英文 :

#include <iostream>
#include <cassert>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <Windows.h>
using namespace std;
char randomLetter()
{
    srand(time(0));
    char rValue;
    while(1)
    if((rValue=(rand()/129)) > 31) 
        return rValue;
}

int main()
{       
    vector<char> meegaString;
    for(int i=0; i < 10000000000; i++)
    {   
        meegaString.push_back(randomLetter());
                if(!(i%10000000)) 
            cout<<"There are: " <<i+1<<" chars in the list"<<endl;
    }
    system("pause");
    return 0;
}

运行此程序之前的 RAM 使用率约为 2500/8000 MB。当涉及到 3200 时,会引发以下异常:

资源 gormandizer .exe 中0x773c15de处未处理的异常: Microsoft C++异常:内存位置的 std::bad_alloc 0x0045f864..

1)为什么这个程序没有填满整个可用内存,尽管它在64位操作系统上运行?

2)为什么只有26%的处理器(英特尔酷睿i5)在使用中?

  1. 如前所述,向量的元素是连续存储的。此外,根据实现 std::vector 时使用的内存分配算法,它可能正在尝试提前预分配内存;分配比用于减少malloc/new调用次数更多的内存。因此,它可能会达到请求比 32 位操作系统可以支持的内存更多的地步(这可以解释为什么 64 位进程可以工作,但 32 位进程不会,尽管有足够的可用内存)。

  2. 您的进程在 4 个内核中的一个内核上运行,并且非常繁忙,因此它占用了大约 25% 的 CPU 时间。其他过程将构成其余部分。

另请参阅:明智地分配矢量内存

Anthony-Arnold的回答并没有错,如果我们对他的措辞有一些冒昧的话,但仍然缺少一些东西。

正如其他人所提到的,如果你的酷睿i5是四核(都是i5的四核吗?),那么25%的人可能会暗示其中一个核心(即你的进程所在的核心)几乎100%繁忙,而其他大部分都是空闲的。 与 anthony-arnold 的回答相反,这 25% 并不表示其他进程占用了另外 75%,而是说其他 75% 的可用 CPU 时间只是浪费(空闲)。 同样,如果您的 CPU 是四核,如果没有多线程测试应用程序,您的测试应用程序将无法消耗超过 25% 的整体。

如果您正在寻找内存空间耗尽、打折内存分配碎片和其他开销,您找到了。 正如其他人所建议的那样,您的应用程序似乎是作为 32 位应用程序构建的。 即使在 64 位操作系统上运行,你的应用也永远无法寻址超过 32 位地址空间可以容纳的限制,即 4Gb。 即便如此,还有很多其他开销,包括为操作系统保留的虚拟地址空间、程序和共享库空间、堆栈空间和分配给其他事物的堆空间以及堆空间开销。 因此,您的meegaString矢量甚至永远不会接近完整的4Gb,甚至可能不会接近2Gb(如果构建为大地址空间感知应用程序,则可能会超过2Gb)。

现在关于Anthony-arnold提到的"前向分配"点:所有STL容器都对摊销操作时间做出承诺。 std::vector 类承诺,平均而言(即摊销),push_back() 操作将是常量时间(即 O(1)),这意味着随着其内容变得越来越大,执行 push_back() 将不需要更长的时间(如果是这样,它将是 O(n))。 有时执行 push_back() 需要比 O(1) 多得多的时间,因为偶尔 push_back() 会导致容器的数据超过其当前分配的空间,并且它需要执行重新分配并将其当前内容移动到新位置,并删除其旧内容。 在操作系统的合作下,一个实现良好的自定义编写的 STL 实现可以通过玩虚拟内存和 MMU 的技巧来做得更好,这样它就不必实际移动内容,它只是告诉操作系统告诉 MMU 使数据的虚拟内存页面映射到新位置, 但这完全是另一个问题,无论如何你都不需要担心它,因为它会在幕后发生。 无论如何,是的,std::vector 类必须在进行新分配时"预分配"比所需更大的内存块,因为这是它可以承诺 O(1) push_back() 时间的唯一方法。 如果每次执行 push_back() 时都必须将内容移动到新分配的缓冲区,那么 push_back() 的时间复杂度将是 O(n),而不是 O(1),因为执行 push_back() 的时间会越来越长,矢量的数据越大。

矢量类模板实现一个动态数组,这需要一个连续的内存块。

关闭主题 - 为此,可以使用列表容器,但堆栈似乎是最好的解决方案。但是,无论是列表还是堆栈,它仍然会崩溃并出现相同的错误(现在接近 4600 MB)。看起来很相似,但现在这不是所选无效数据结构的错误。发生这种情况是因为 32 位应用程序具有非常有限的可用内存,因此为了完全填充它,请在 x64 平台上编译此程序。

#include <iostream>
#include <stack>
#include <ctime>
#include <cstdlib>

using namespace std;
char randomLetter()
{
    srand(time(0));
    char rValue;
    while(1)
    if((rValue=(rand()/129)) > 31) 
        return rValue;
}

int main()
{       
    stack<char> meegaString;
    for(int i=0; i < 10000000000; i++)
    {   
        meegaString.push(randomLetter());
                if(!(i%10000000)) 
            cout<<"There are: " <<i+1<<" chars in the list"<<endl;
    }


    system("pause");
    return 0;
}

最新更新