我正在 Linux 中为 PCIe 设备编写设备驱动程序。该设备驱动程序执行多次读写以测试吞吐量。当我使用 memcpy 时,TLP 的最大负载是 8 字节(在 64 位架构上)。在我看来,获得 16 字节有效负载的唯一方法是使用 SSE 指令集。我已经看过 this但代码无法编译(AT&T/Intel 语法问题)。
- 有一种方法可以在 linux 中使用该代码吗?
- 有谁知道我在哪里可以找到移动 128 位的 memcpy 的实现?
最佳答案
首先,您可能使用 GCC 作为编译器,它使用 asm
语句作为内联汇编程序。使用它时,您必须为汇编代码使用字符串文字(在发送到汇编程序之前将其复制到汇编代码中 - 这意味着该字符串应包含换行符)。
其次,您可能不得不为汇编器使用 AT&T 语法。
第三个 GCC 使用 extended asm在汇编程序和 C 之间传递变量。
第四,无论如何,您应该尽可能避免使用内联汇编程序,因为编译器不可能通过 asm
语句安排指令(至少这是真的)。相反,您可以使用 GCC 扩展,例如 vector_size
属性:
typedef float v4sf __attribute__((vector_size(16)));
void fubar( v4sf *p, v4sf* q )
{
v4sf p0 = *p++;
v4sf p1 = *p++;
v4sf p2 = *p++;
v4sf p3 = *p++;
*q++ = p0;
*q++ = p1;
*q++ = p2;
*q++ = p3;
}
的优点是,即使您为没有 mmx
寄存器但可能是其他一些 128 位寄存器(或没有 vector )的处理器编译,编译器也会生成代码完全注册)。
第五,您应该调查提供的 memcpy
是否不够快。 memcpy
通常是真正优化过的。
第六,如果你在 Linux 内核中使用特殊寄存器,你应该采取预防措施,有些寄存器在上下文切换期间不会被保存。 SSE 寄存器是其中的一部分。
第七,当你使用它来测试吞吐量时,你应该考虑处理器是否是等式中的一个重要瓶颈。将代码的实际执行与从 RAM 读取/写入(您命中还是未命中缓存?)或从外围设备读取/写入进行比较。
第八,在移动数据时,你应该避免将大块数据从 RAM 移动到 RAM,如果它是到/从带宽有限的外围设备,你绝对应该考虑为此使用 DMA。请记住,如果访问时间限制了性能,CPU 仍将被视为繁忙(尽管它不能以 100% 的速度运行)。
关于c - memcpy 在 Linux 中移动 128 位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34003003/