为什么Java API会使用int,何时short甚至byte是足够的?
示例:DAY_OF_WEEK类中的字段Calendar使用int.
如果差异太小,那么为什么存在这些数据类型(short,int)?
我找不到一个体面的文档来解释对齐系统如何工作以及为什么某些类型比其他类型更严格一致.
通常有两种类型的SIMD指令:
A.使用对齐的内存地址的那些,如果地址未在操作数大小边界上对齐,则会引发一般保护(#GP)异常:
movaps xmm0, xmmword ptr [rax]
vmovaps ymm0, ymmword ptr [rax]
vmovaps zmm0, zmmword ptr [rax]
Run Code Online (Sandbox Code Playgroud)
B.以及使用未对齐内存地址的那些,不会引发此类异常:
movups xmm0, xmmword ptr [rax]
vmovups ymm0, ymmword ptr [rax]
vmovups zmm0, zmmword ptr [rax]
Run Code Online (Sandbox Code Playgroud)
但是我只是好奇,为什么我要用脚射击自己并使用第一组的对齐记忆指令呢?
谁能告诉我std :: atomic :: is_lock_free()是否像constexpr一样不是静态的?使它为非静态和/或为非constexpr对我来说没有意义。
struct details_state {
struct details_status D1;
struct details_status D2;
};
struct details {
struct details_state details_states[2];
} __attribute__((packed));
struct details *p;
void print_details_status(struct details_status *s)
print_details_status(&(p->details_states[i].D1));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
警告:获取“结构详细信息”的打包成员的地址可能会导致未对齐的指针值 [-Waddress-of-packed-member]
GCC 在 >9 版本中给出此警告。如何在不使用 [-Wno-address-of-packed-member] 的情况下摆脱此警告
在答案中,我已经声明未对齐访问的速度与对齐访问的速度几乎相同(在x86/x86_64上).我没有任何数字来支持这个陈述,所以我已经为它创建了一个基准.
你看到这个基准测试有什么缺陷吗?你可以改进它(我的意思是,增加GB /秒,所以它更好地反映了真相)?
#include <sys/time.h>
#include <stdio.h>
template <int N>
__attribute__((noinline))
void loop32(const char *v) {
for (int i=0; i<N; i+=160) {
__asm__ ("mov (%0), %%eax" : : "r"(v) :"eax");
__asm__ ("mov 0x04(%0), %%eax" : : "r"(v) :"eax");
__asm__ ("mov 0x08(%0), %%eax" : : "r"(v) :"eax");
__asm__ ("mov 0x0c(%0), %%eax" : : "r"(v) :"eax");
__asm__ ("mov 0x10(%0), %%eax" : : "r"(v) :"eax");
__asm__ ("mov 0x14(%0), %%eax" : : "r"(v) :"eax");
__asm__ ("mov 0x18(%0), %%eax" : : "r"(v) :"eax"); …Run Code Online (Sandbox Code Playgroud) 我在内存中有大量 64 位值。不幸的是,它们可能不会与 64 位地址对齐。我的目标是改变所有这些值的字节序,即交换/反转它们的字节。
我知道bswap交换 32 位或 64 位寄存器字节的指令。但是因为它需要一个寄存器参数,所以我不能将它传递给我的内存地址。当然我可以先将内存加载到寄存器中,然后交换,然后写回:
mov rax, qword [rsi]
bswap rax
mov qword [rsi], rax
Run Code Online (Sandbox Code Playgroud)
但这是否正确,因为地址可能未对齐?
另一种可能性是手动进行交换:
mov al, byte [rsi + 0]
mov bl, byte [rsi + 7]
mov byte [rsi + 0], bl
mov byte [rsi + 7], al
mov al, byte [rsi + 1]
mov bl, byte [rsi + 6]
mov byte [rsi + 1], bl
mov byte [rsi + 6], al
mov al, byte [rsi + 2]
mov bl, …Run Code Online (Sandbox Code Playgroud) 让我们用一个简单的C代码来设置寄存器:
int main()
{
int *a = (int*)111111;
*a = 0x1000;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我使用1级优化编译ARM(arm-none-eabi-gcc)代码时,汇编代码如下:
mov r2, #4096
mov r3, #110592
str r2, [r3, #519]
mov r0, #0
bx lr
Run Code Online (Sandbox Code Playgroud)
看起来地址111111被解析为最接近的4K边界(110592)并移动到r3,然后通过将519添加到110592(= 111111)来存储值4096(0x1000).为什么会这样?
在x86中,程序集很简单:
movl $4096, 111111
movl $0, %eax
ret
Run Code Online (Sandbox Code Playgroud) 我有以下Java代码(所有数组在我们调用“arrays”之前都已初始化,并且所有数组的大小均为“arraySize”)
int arraySize = 64;
float[] a;
float[] b;
float[] result;
public void arrays() {
for (int i = 0; i < arraySize; i++) {
result[i] = ((a[i] * b[i] + b[i] - b[i]) / b[i]) +
a[i] + a[i] + a[i] + a[i];
}
}
Run Code Online (Sandbox Code Playgroud)
JIT 的输出是:
# {method} {0x00000001034751a8} 'arrays' '()V' in 'main/ComplexExpression'
# [sp+0x30] (sp of caller)
[Entry Point]
0x000000010c4c55a0: mov 0x8(%rsi),%r10d
0x000000010c4c55a4: movabs $0x800000000,%r11
0x000000010c4c55ae: add %r11,%r10
0x000000010c4c55b1: cmp %r10,%rax
0x000000010c4c55b4: jne 0x000000010c44b780 ; {runtime_call ic_miss_stub} …Run Code Online (Sandbox Code Playgroud) 我正在学习 C avx 内在函数,我想知道它是如何工作的。
我很熟悉我可以做这样的事情:
__m256 evens = _mm256_set_ps(2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0);
Run Code Online (Sandbox Code Playgroud)
这里我存储 8 个 32 位浮点数。所以这是 256 位。
但是假设我正在编写一个线性代数库。然后我如何处理任意数量的向量;例如,如何将 10 个 32 位浮点数放入 avx 向量中?
如果您能提供一些例子,我将非常感激