DMD 中的 memcmp v.s GDC AND std.parallelism:并行
memcmp in DMD v.s GDC AND std.parallelism: parallel
我正在实现一个带有指向某些手动管理内存的指针的结构。这一切都适用于 DMD,但当我使用 GDC 对其进行测试时,它在 opEquals
运算符重载时失败。我已经将它缩小到 memcmp。在 opEquals
中,我将指向内存的指针与 memcmp 进行了比较,它在 DMD 中的行为与我预期的一样,但在 GDC 中却失败了。
如果我返回并通过对内置类型使用 ==
一次比较存储在手动管理的内存 1 中的每个值来编写 opEquals
方法,它在两个编译器中都有效。我更喜欢 memcmp 路由,因为它写起来更短,而且看起来应该更快(更少的间接、迭代等)。
为什么?这是一个错误吗?
(我使用 C 的经验是 10 年前的,一直使用 python/java 从那以后,我在 C 中从未遇到过这种问题,但我没有那么多地使用它。)
编辑:
我正在比较的内存表示 'real' 值的二维数组,我只是希望将它分配到一个块中,这样我就不必处理锯齿状的数组。我将在紧密循环中大量使用这些结构。基本上我正在滚动我自己的矩阵结构,它将(最终)缓存一些常用的值(迹线、行列式)并提供一个替代的只读视图到不需要复制它的转置。我计划使用大约 10x10 到大约 1000x1000 的矩阵(尽管并不总是正方形)。
我还计划实现一个通过 ubyte[]
使用 GC 分配内存的版本并分析这两个实现。
编辑 2:
好的,我尝试了几件事。我也有一些 parallel
循环,我有一种预感,这可能是问题所在。所以我添加了一些版本声明来制作并行和非并行版本。为了让它与 GDC 一起工作,我不得不使用非并行版本并将 real
更改为 double
。
GDC下编译的所有案例。但是单元测试失败了,并不总是在同一行上,而是在我使用 real
或 parallel
时始终在 opEquals
调用处。在DMD下所有情况下编译运行都没问题
谢谢,
real
的大小有点奇怪:它是 80 位数据,但是如果你检查 real.sizeof,你会发现它比那个大(至少在 Linux,我认为它在 Windows 上有 10 个字节,我敢打赌你不会在那里看到这个错误)。原因是确保它在字边界上对齐 - 四个字节的倍数 - 以便处理器在数组中更有效地加载。
每个数据元素之间的字节称为填充,它们的内容并不总是定义的。我自己还没有证实这一点,但是@jpf 对这个问题的评论说的和我的直觉一样,所以我现在把它作为答案发布。
D 中的 is
运算符与 memcmp(&data1, &data2, data.sizeof)
的作用相同,因此@jpf 的评论和您的 memcmp
是一回事。它检查数据和填充,而 == 只检查数据(顺便说一句,它对浮点类型做了一些特殊处理,因为它还比较 NaN,所以确切的位模式对这些检查很重要;实际上,我的第一个直觉是当我看到题名是NaN相关!但不是这样)
无论如何,显然 dmd 也会初始化填充字节,而 gdc 不会,将其留作垃圾,并不总是匹配。
我正在实现一个带有指向某些手动管理内存的指针的结构。这一切都适用于 DMD,但当我使用 GDC 对其进行测试时,它在 opEquals
运算符重载时失败。我已经将它缩小到 memcmp。在 opEquals
中,我将指向内存的指针与 memcmp 进行了比较,它在 DMD 中的行为与我预期的一样,但在 GDC 中却失败了。
如果我返回并通过对内置类型使用 ==
一次比较存储在手动管理的内存 1 中的每个值来编写 opEquals
方法,它在两个编译器中都有效。我更喜欢 memcmp 路由,因为它写起来更短,而且看起来应该更快(更少的间接、迭代等)。
为什么?这是一个错误吗?
(我使用 C 的经验是 10 年前的,一直使用 python/java 从那以后,我在 C 中从未遇到过这种问题,但我没有那么多地使用它。)
编辑:
我正在比较的内存表示 'real' 值的二维数组,我只是希望将它分配到一个块中,这样我就不必处理锯齿状的数组。我将在紧密循环中大量使用这些结构。基本上我正在滚动我自己的矩阵结构,它将(最终)缓存一些常用的值(迹线、行列式)并提供一个替代的只读视图到不需要复制它的转置。我计划使用大约 10x10 到大约 1000x1000 的矩阵(尽管并不总是正方形)。
我还计划实现一个通过 ubyte[]
使用 GC 分配内存的版本并分析这两个实现。
编辑 2:
好的,我尝试了几件事。我也有一些 parallel
循环,我有一种预感,这可能是问题所在。所以我添加了一些版本声明来制作并行和非并行版本。为了让它与 GDC 一起工作,我不得不使用非并行版本并将 real
更改为 double
。
GDC下编译的所有案例。但是单元测试失败了,并不总是在同一行上,而是在我使用 real
或 parallel
时始终在 opEquals
调用处。在DMD下所有情况下编译运行都没问题
谢谢,
real
的大小有点奇怪:它是 80 位数据,但是如果你检查 real.sizeof,你会发现它比那个大(至少在 Linux,我认为它在 Windows 上有 10 个字节,我敢打赌你不会在那里看到这个错误)。原因是确保它在字边界上对齐 - 四个字节的倍数 - 以便处理器在数组中更有效地加载。
每个数据元素之间的字节称为填充,它们的内容并不总是定义的。我自己还没有证实这一点,但是@jpf 对这个问题的评论说的和我的直觉一样,所以我现在把它作为答案发布。
D 中的 is
运算符与 memcmp(&data1, &data2, data.sizeof)
的作用相同,因此@jpf 的评论和您的 memcmp
是一回事。它检查数据和填充,而 == 只检查数据(顺便说一句,它对浮点类型做了一些特殊处理,因为它还比较 NaN,所以确切的位模式对这些检查很重要;实际上,我的第一个直觉是当我看到题名是NaN相关!但不是这样)
无论如何,显然 dmd 也会初始化填充字节,而 gdc 不会,将其留作垃圾,并不总是匹配。