【问题标题】:C++ program stability after millions of executions数百万次执行后的 C++ 程序稳定性
【发布时间】:2013-09-21 23:39:20
【问题描述】:

我有一个 C++ 程序,主要执行矩阵乘法、加法等操作。

问题是,当计算执行大约 300 万次时会发生 EXC_BAD_ACCESS。

当一个问题被执行数百万次和几个小时时,是否会出现任何可能的问题?

节目详情:

该程序只是对不同范围的值进行计算,因此它同时在 6 个线程上执行。线程之间没有资源共享。

程序中似乎没有明显的问题,因为:

  1. 没有内存泄漏,我用 Instruments 确认过,程序内存大小稳定。
  2. 该程序可以在每个线程上执行至少 200 万次而没有任何问题,但几乎可以保证 EXC_BAD_ACCESS 异常在某个时间出现在某个线程上。 (异常发生在我对程序的 2 次尝试中(2/2))

关于矩阵乘法:

有时矩阵的大小约为 2*2 乘以 2*1000。

矩阵的元素是一个自定义的复数类。

元素的值由 rand() 随机生成并转换为浮点数。

结构是这样的:

class Complex
{
private:
    float _real, _imag;
public:
   // getters, setters and overloaded operators
};

class Matrix
{
private:
    Complex **_values;
    int _row,_col;
public:
     getters, setters and overloaded operators
};

非常感谢!

非常欢迎任何可能的崩溃原因!

【问题讨论】:

  • EXC_BAD_ACCESS 通常意味着代码中的错误或不稳定的硬件。
  • 程序不会老化。如果一个程序不包含任何错误,它可以无限期地运行。调试器将帮助您找到错误。
  • 如果您在几个小时内非常努力地驱动 CPU 并最终导致崩溃,但您确信您的代码是正确的,那么需要检查的一件事是确保您的计算机没有过热。 (对不起,如果这听起来很愚蠢,但你确实问了任何可能的原因......)
  • Ubuntu 不会让你的程序突然运行得更正确 :)
  • 您将结果写入哪里?那里有线程覆盖的机会吗?您是否在调用任何非线程安全的运行时函数?

标签: c++ multithreading matrix stability


【解决方案1】:

EXC_BAD_ACCESS 表示您取消引用了一个未指向进程当前内存空间的指针。这是您的代码中的一个错误。在调试器下运行它直到它失败,然后查看它失败的语句中的变量值。它可能很简单,也可能非常微妙。

【讨论】:

  • 是的,进程的内存空间......这似乎是解决方案,正如#Graham Perks 在上面也指出的那样,问题似乎与线程有关。
  • 问题确实与内存空间有关,也许#Graham Perks 指出的更清楚,但是当我在没有多线程的情况下运行程序时,它可以循环任何我想要的次数。
【解决方案2】:

您的帖子中的信息太少,无法做出决定性的回答。但是,您现在可能没有可用的信息会改变它,您需要更仔细地调试案例。这就是我要做的。

要调试,您需要可重复性。但是……你说你使用的是随机数。不过,您的程序所做的似乎是一些科学计算。在大多数情况下,您实际上并不需要“真正的”随机性,而是“可重复的”随机性——通过统计测试的随机性,但是您有足够的数据来重置随机数生成器,以便它产生与中完全相同的结果上一次运行。为此,您可以在每次开始新的计算块时记下当前的 RNG 状态(例如种子)。

现在,编写一段代码来存储所有必要的状态,以便每隔几分钟重新启动一次计算(包括 RNG),然后运行程序。这样,如果您的代码崩溃,您将能够以相同的确切状态重新开始计算并到达崩溃的地步,而无需等待数百万次迭代。我在这里提出一个强有力的假设,即除了 RNG,您的代码不依赖于任何其他类型的外部状态(例如,网络活动、IO、进程调度程序在调度线程时做出某些选择……)

有了这类数据,就可以更轻松地测试问题是否是由于机器故障(过热、内存不足等)造成的。只需使用崩溃前的最后一个状态重新启动计算 - 最好在让机器冷却之后,也许重新启动它......如果你会遇到另一个崩溃(每次尝试重新启动代码时都会发生),很确定这是由于代码中的错误。

如果不是,我们仍然不能说这是机器故障 - 您的代码可能(由于代码中的纯意外/错误)由于取决于您无法控制的因素的未定义行为而崩溃。示例包括在很少使用的代码路径中使用未初始化的指针:它有时可能会引发错误的访问,并且如果纯粹运气指针指向您分配的内存,则不会被注意到。试试valgrind,这可能是检查内存问题的最佳工具……除了它会大大减慢执行速度,以至于你会再次选择从已知可疑的状态(崩溃前的最后一个状态)重新运行计算等待数百万次迭代。我已经看到了 5 倍到 100 倍的减速。

同时,尝试在另一台机器上运行您的代码。如果在类似数量的迭代后你也会崩溃(确保等待至少比原始机器崩溃多 3 倍的迭代次数),那么很可能这是你的代码中的一个错误。

黑客愉快!

【讨论】:

  • 感谢您的提示!是的,我正在做一些科学计算并使用 C++,因为它比 Matlab 编写 OO 代码更清晰,而且速度更快。我将检查 valgrind 的内存访问问题并尝试记录 RGN 状态。
【解决方案3】:

有限精度的计算在几百万次迭代后失败?这可能是累积的舍入误差。问题是,这些通常表现为除以零或其他数学错误。 EXC_BAD_ACCESS 不是。但是,有一种情况会发生这种情况:当您将数学结果用作数组索引时。

【讨论】:

  • 谢谢,但正如#Graham Perks 和#EJP 所指出的,问题很可能与线程和内存覆盖有关。我把程序从6线程改成了4线程,现在已经运行了11小时54分钟,没有问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-27
  • 1970-01-01
  • 2016-05-02
  • 2014-12-12
  • 2019-06-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多