This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] 编译器/TMS320C6678:NaN 通过日志计算输出。

Guru**** 1960255 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/724592/compiler-tms320c6678-nan-is-output-by-log-calculation

器件型号:TMS320C6678

工具/软件:TI C/C++编译器

我正在 C6678上进行开发。

我在每个内核上调用了以下函数。

void Func ()
{
float temp1 = log ((double) 2.0f);
platform_write ("1:%e\n"、temp1);
float temp2 =(float) log (2.0f);
platform_write ("2:%e\n"、temp2);
float temp3 = logf (2.0f);
platform_write ("3:"4
:
%e、temp4);platform_temp4 ("4:"、temp4);platform_temp4 (temp3:\n"temp4:"(temp4)

*"platform_write"函数是我自己的 printf 函数。

首次调用函数的结果。
内核1至8

1:6.931472e-01
2:6.931472e-01
3:6.931472e-01
4:6.931472e-01

第二次调用函数的结果。

内核1至7

1:6.931472e-01
2:6.931472e-01
3:6.931472e-01
4:6.931472e-01 

内核8

1:nan
2:nan
3:6.931472e-01
4:nan

为什么只有在第二次调用函数时内核8才变为 nan?

CCS 版本:6.2.0
处理器 SDK 版本:03.01.00.06

1:南

2:南

3:6.931472e-01

4:南

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    抱歉、最后4行没有意义。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    我已通知 RTOS 团队。 他们将直接在此处发布反馈。

    此致、
    Yordan
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    所有内核是否都从同一位置运行 DDR 或 MSMC 存储器中的代码? 是否已为所有内核启用高速缓存?  您能否在 core8上设置断点并在调用 log 函数之前和之后检查 temp 变量的值。

    [引用 USER="user1432743"]为什么第二次调用函数时内核8才变为 nan?

    计算是否第一次打印正确的值、第二次仅出现此问题? 我怀疑某些内存损坏问题可能会导致这种情况、因此最好设置断点、并确保内存未因某些操作而损坏。 此外、如果从同一个存储器执行、您能否确保在执行数据访问时有一些同步。 您n`t 使用信标或标志以及内核 ID 来确保内核不会相互破坏工作空间。

    此致、

    Rahul

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你好。 感谢你的答复。

    >是否所有内核都从同一位置运行 DDR 或 MSMC 存储器中的代码?
    是的。 所有内核都从 DDR 运行代码。

    >是否已为所有内核启用高速缓存?
    否 所有 L2 (SRAM)都是存储器设置。

    >能否在 core8上设置断点并在调用 log 函数之前和之后检查 temp 变量的值。
    我重新编写了下面的函数并显示了结果。
    void Func (){
    浮点 temp1 = 0.f;
    浮点 temp2 = 0.f;
    浮点 temp3 = 0.f;
    浮点 temp4 = 0.f;
    platform_write ("1:%e\n"、temp1);
    TEMP1 = log ((double) 2.0f);
    platform_write ("1:%e\n"、temp1);
    platform_write ("2:%e\n"、temp2);
    TEMP2 =(浮点) log (2.0f);
    platform_write ("2:%e\n"、temp2);
    platform_write ("3:%e\n"、temp3);
    temp3 = logf (2.0f);
    platform_write ("3:%e\n"、temp3);
    platform_write ("4:%e\n"、temp4);
    temp4 = log (2.0);
    platform_write ("4:%e\n"、temp4);


    1:0.000000e+00
    1:南
    2:0.000000e+00
    2:南
    3:0.000000e+00
    3:6.931472e-01
    4:0.000000e+00
    4:南

    值在日志计算之前正确显示。 但是、值会随着对数计算而变为 nan。

    >计算是否第一次打印正确的值,而第二次仅出现此问题?
    是的。

    >我怀疑某些内存损坏问题可能会导致这种情况、因此最好设置断点、并查看内存未因某些操作而损坏。
    在日志计算之前显示正确的值。 此外、temp3不是 nan。 因此、计算结果似乎有问题、而不是内存损坏。如果内存损坏是原因、我认为该值在日志计算之前是 nan。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    对于调试、您能否将 platform_write 更改为 printf 并使用 CCS 中的 CIO 控制台来检查输出。 目前尚不清楚 RTS 库中的日志函数是否出现中断、或者是否是 platform_write 导致了该问题。 转到标准 IO 函数将消除该变量。

    此致、
    Rahul
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我将 platform_write 更改为 printf 并使用 CIO 控制台确认了输出。 结果如下。

    [仅 printf]
    1:0.000000e+00
    1:6.931472e-01
    2:0.000000e+00
    2:6.931472e-01
    3:0.000000e+00
    3:6.931472e-01
    4:0.000000e+00
    4:6.931472e-01

    我尝试了 platform_write 和 printf。
    [printf 和 platform_write]
    1:0.000000e+00
    1:6.931472e-01
    2:0.000000e+00
    2:6.931472e-01
    3:0.000000e+00
    3:6.931472e-01
    4:0.000000e+00
    4:6.931472e-01

    上次仅尝试 platform_write。
    [仅限 platform_write ]
    1:0.000000e+00
    1:南
    2:0.000000e+00
    2:南
    3:0.000000e+00
    3:6.931472e-01
    4:0.000000e+00
    4:南


    我们将优化级别从3更改为2、从而丢失 printf 和 platform_write。 然后、正确计算了它。

    总结了结果。
    ·当优化级别从3更改为2时、将正确计算。
    ·在 log (2.f)中未正确计算它、但在 logf (2.f)中正确计算它。
    ·当使用 printf 打印 log (2.f)值时、会正确计算该值。 使用 platform_write 无法正确计算。

    我仍然不明白为什么会发生这种情况。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我将这一n`t 移至编译器论坛、供专家们评论-O3和-O2之间的行为差异、因为这似乎是库的器件问题。

    此致、
    Rahul
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如果日志在一个内核上正常工作、则它应在所有内核上正常工作。 编译器完全不知道您在哪个内核上运行。

    是否确定在内核8上运行的程序的文件调用日志中包含了 math.h? 您遇到的错误种类与忘记包含 math.h 时可能发生的情况非常相似
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    >是否确定在核心8上运行的程序的文件调用日志中包含 math.h?
    是的。 我已经包含了 math.h。
    (如果不包含 math.h、我认为编译将不会通过。)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="user1432743"](如果不包含 math.h,我认为编译将不会通过)

    嗯、对于大多数 C 程序来说、情况并非如此。  如果不包含 math.h、编译器将根据参数类型和"默认参数促销"来猜测函数的原型。  您不需要弄清楚这一点;只需在使用数学函数时始终仔细检查您是否包含 math.h。  通过添加编译器选项--diag_error=225可以实现额外的安全性、以便编译器在忘记包含 math.h 时发出错误

    现在、对于手头的错误、程序中只有一个日志副本。  如果它在 Core 1上正常运行、它将在每个 Core 上正常工作。  同样、如果它在第一次调用时正常运行、它应该在第二次调用时正常运行。  我强烈怀疑错误不在日志本身中、而是在调用日志的代码中。

    请注意、您正在调用两个不同的函数、log 和 logf。  尽管它们执行相同的操作、但它们使用不同的精度来执行、因此它们是两个不同的功能。  另请注意、在您的示例中、logf 始终返回正确的答案。

    现在、我们需要讨论类型转换。  函数日志采用 double 操作数并返回 double 结果。  函数 logf 采用浮点操作数并返回浮点结果。  编译器将根据需要插入类型转换、以强制参数为正确的类型。

    当您调用 log(double)2.0f)时,您会得到您所期望的... 编译器将浮点常量2.0f 转换为双精度值(2.0)并将其传递给 log。

    另一方面、当您调用 log (2.0f)时、编译器会再次将浮点常量转换为双精度值(2.0)并传递该值。

    调用 log2.0时、编译器不进行转换、并将双精度值(2.0)传递给 log。

    编译器还将根据需要插入类型转换、以便在将这些函数的返回值分配给变量"tempN"之前转换这些函数的返回值。

    写入"temp1 = log ((double) 2.0f)"时、编译器会将 log 的双精度结果(大约为0.69)转换为浮点值(大约为0.69f)、并将其分配给 temp1。

    写入"temp2=(float)log (2.0f)"时,已经将日志的双精度结果转换为带显式转换的浮点值。

    写入"temp4 = log (2.0)"时、编译器再次插入双返回值(0.69)到浮点值(0.69f)的隐式转换

    因此、在涉及 temp1、temp2和 temp4的测试行中、您应该期望它们始终获得完全相同的答案、因为您正在调用具有相同值的相同函数(log)(2.0完全可以表示为2.0f、无舍入误差)、 并在转换为浮点(0.69f)后获得相同的结果。

    现在、它变得有点奇怪。

    将浮点类型传递给可变参数函数时(具有... 参数)、例如 printf 或 platform_write、编译器会执行"默认参数升级"。  具体而言、在传递到 platform_write 之前、任何类型为"float"的值都将转换为"double"。  platform_write 的实现必须使用 va_arg (ap、double)来获取双精度值;它不会是浮点值。  请仔细检查。  此外、在调用此类函数之前、您需要在示波器中具有有效的原型。  对于 printf、必须包含 stdio.h  对于您的函数、必须按如下方式进行原型设计:int platform_write (const char *、...)。  如果调用 platform_write 时看不到该原型、则会发生各种奇怪的情况。

    好的、现在您应该首先检查的简单事项已经不能解决了、让我们来考虑一下症状。

    在开始生成错误值之前、您会显示函数至少返回一次正确的值-这不是数学函数的工作方式。  在给定相同输入的情况下、它们应每次返回相同的输出。  我怀疑输入已经改变。  了解编译器的工作原理后、我知道编译器会将所有常量参数转换为 log、然后将它们存储在常量表中。  尽管日志参数在源代码中具有不同类型、但它们都可以由单个双精度常量表示、如上所述。  logf 的参数将是单独的常量、因为它将作为浮点常量保留。  现在、假设通过一些杂散指针进行的一些写入碰巧写入常数表、而恰好是在常数2.0上插入。  现在、编译器将从常量表中进行加载、以将值传递给日志、而不知道该值在其他位置已损坏。  这将解释您在一段时间内获得正确答案的症状、然后突然得到虚假答案。  这里的问题是杂散指针可能来自任何地方;可能是编译器中的错误、可能是应用程序中的错误。  如果不查看整个程序、就不可能排除这种可能性。

    您至少应该在 Func 中设置一个断点并观察传递给 log 的值;您应该看到一个双精度值正在从常量表加载并写入 A4 [编辑--archaeology]。  了解该双精度值是否正确将极大地帮助确定在何处查找错误。

    总之:

    • 我怀疑这里有编译器错误、因为症状与我预期的编译器错误不符。
    • 在编译器团队开始研究之前、需要进行更多分析。
    • 我打赌的是一个内存编号问题。

x 出现错误。请重试或与管理员联系。