c - memcpy 在 Linux 中移动 128 位

标签 c linux assembly sse simd

我正在 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/

相关文章:

c++ - 为什么有人需要指向指针的指针?

c - putchar() 没有返回值?

c++ - 没有有用且可靠的方法来检测 C/C++ 中的整数溢出?

C 无符号整型 x = 1;小于 int y = -1;

c - Linux下实现窗口函数InterlockedExchange

c++ - 文本迭代,汇编与 C++

c++ - 如何从 LLVM 中的终止符指令中删除后继指令

php - MySQL 到 outfile 不能在 PHP 应用程序中工作,但可以在 mysql 中工作

linux - Wav 到 mp3 bash 脚本

使用内联汇编 ia32 将指针更改为包含在结构体中的数组