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.
工具/软件: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:南
所有内核是否都从同一位置运行 DDR 或 MSMC 存储器中的代码? 是否已为所有内核启用高速缓存? 您能否在 core8上设置断点并在调用 log 函数之前和之后检查 temp 变量的值。
[引用 USER="user1432743"]为什么第二次调用函数时内核8才变为 nan?
计算是否第一次打印正确的值、第二次仅出现此问题? 我怀疑某些内存损坏问题可能会导致这种情况、因此最好设置断点、并确保内存未因某些操作而损坏。 此外、如果从同一个存储器执行、您能否确保在执行数据访问时有一些同步。 您n`t 使用信标或标志以及内核 ID 来确保内核不会相互破坏工作空间。
此致、
Rahul
[引用 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]。 了解该双精度值是否正确将极大地帮助确定在何处查找错误。
总之: