这是一个有点低级别的问题.在x86程序集中有两个SSE指令:
MOVDQA xmmi, m128
和
MOVNTDQA xmmi, m128
IA-32软件开发人员手册说MOVNTDQA 中的NT代表非时间性,否则它与MOVDQA相同.
我的问题是,非时间意味着什么?
我将应用程序移植到C中的ARM平台,该应用程序也在x86处理器上运行,并且必须向后兼容.
我现在有一些变量对齐的问题.我已经阅读了gcc手册,因为
__attribute__((aligned(4),packed))我解释了所说的内容,因为struct的开头与4字节边界对齐,并且由于packed语句,内部保持不变.
最初我有这个,但偶尔它与4字节边界不对齐.
typedef struct
{
unsigned int code;
unsigned int length;
unsigned int seq;
unsigned int request;
unsigned char nonce[16];
unsigned short crc;
} __attribute__((packed)) CHALLENGE;
Run Code Online (Sandbox Code Playgroud)
所以我把它改成了这个.
typedef struct
{
unsigned int code;
unsigned int length;
unsigned int seq;
unsigned int request;
unsigned char nonce[16];
unsigned short crc;
} __attribute__((aligned(4),packed)) CHALLENGE;
Run Code Online (Sandbox Code Playgroud)
该明白我前面所说似乎是不正确的,这两个结构是现在对齐到4字节边界,和现在的内部数据对齐到四个字节边界,但因为尾结构,该结构的大小已增加大小从42到44个字节.这个大小是至关重要的,因为我们有其他依赖于结构为42字节的应用程序.
有些人可以向我描述如何执行我需要的操作.任何帮助深表感谢.
在x86处理器上有没有办法将数据从常规写回内存加载到寄存器而不通过缓存层次结构?
我的用例是我有一个很大的查找结构(Hash map或B-Tree).我正在处理大量的数字(比我的L3大得多但适合内存).我想做的很简单:
int result = 0;
for (num : stream_numbers) {
int lookup_result = lookup_using_b_tree(num);
result += do_some_math_that_touches_registers_only(lookup_result);
}
return result;
Run Code Online (Sandbox Code Playgroud)
由于我只访问每个数字一次并且所有数字的总和超过L3大小,我想他们最终会驱逐一些缓存行来保存我的B树的一部分.相反,我理想的是不喜欢这个流命中缓存中的任何数字,因为它们根本没有时间局部性(只读一次).这样我可以最大化我的B树保留在缓存中的机会,并且查找速度更快.
我已经查看了(v)movntdqaSSE 4.1中有关时间负载的说明.这似乎不太合适,因为它似乎只适用于组合内存的不可缓存的写入.英特尔的这篇旧文章声称:
未来几代英特尔处理器可能包含流加载的优化和增强功能,例如增加流加载缓冲区的利用率和支持额外的内存类型,为软件开发人员提供更多机会,以提高其应用程序的性能和能效.
但是我今天没有意识到任何这样的处理器.我已经在其他地方读过,处理器可以选择忽略这个回写内存的提示并使用movdqa替代.那么有什么方法可以实现从常规回写内存加载而不通过x86处理器上的缓存层次结构,即使它只能在Haswell和后来的模型上实现?我还要感谢有关未来是否可能的任何信息?