gpt4 book ai didi

c - 从 uint32_t[16] 数组到 uint32_t 变量序列的 64 位副本

转载 作者:太空宇宙 更新时间:2023-11-04 07:53:31 24 4
gpt4 key购买 nike

我已经能够在相同大小的 uint32_t 数组上使用 64 位副本来提高性能,并且想对来自 uint32_t[16] 数组的 16 个 uint32_t 变量序列执行相同的操作。我无法用数组替换变量,因为它会导致性能下降。

我注意到编译器按顺序为一系列已声明的 uint32_t 变量提供指针地址,相反,最后一个变量获得最低地址并增加 4 个字节到第一个声明的变量。我尝试使用该最终变量的起始目标地址并将其转换为 uint64_t * 指针,但这没有用。然而,uint32_t[16] 数组的指针是按顺序排列的。

这是我最近尝试的一个例子。

uint32_t x00,x01,x02,x03,x04,x05,x06,x07,x08,x09,x10,x11,x12,x13,x14,x15;
uint64_t *Bu64ptr = (uint64_t *) B;
uint64_t *x15u64ptr = (uint64_t *) &x15;

/* This is an inline function that does 64-bit eqxor on two uint32_t[16]
& stores the results in uint32_t B[16]*/
salsa8eqxorload64(B,Bx);

/* Trying to 64-bit copy here */
*x15u64ptr++ = *Bu64ptr++;
*x15u64ptr++ = *Bu64ptr++;
*x15u64ptr++ = *Bu64ptr++;
*x15u64ptr++ = *Bu64ptr++;
*x15u64ptr++ = *Bu64ptr++;
*x15u64ptr++ = *Bu64ptr++;
*x15u64ptr++ = *Bu64ptr++;
*x15u64ptr++ = *Bu64ptr++;

我是在追求不可能的事情,还是我的技能不足再次成为阻碍?我检查了x15和x15u64ptr的指针地址值,它们是完全不同的,使用下面的方法。

printf("x15u64ptr %p\n", (void *) x15u64ptr);
printf("x15 %p\n", (void *) &x15);

我有一个想法创建一个数组,并使用 x??变量作为指向数组中各个元素的指针,然后在两个数组上执行 64 位复制,我希望以这种方式将值分配给 uint32_t 变量,但得到了关于 = 赋值无效 ivalue 的编译器失败警告。也许我在语法上做错了什么。使用 64 位 memcpy 替代方案和自定义 64 位 eqxor,我将散列函数的性能提高了 10% 以上,如果我能让它正常工作,我希望这能再提高 5-10%。

*更新 13-09-2018

我结束了使用结构然后基于 NEON 的操作。使用 32 位代码和 memcpy 的原始性能提高 20%。我还能够将技术扩展到 salsa20/8 使用的 add&save 和 eqxor 操作。

struct XX
{
uint32_t x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, x11, x12,x13,x14,x15;
} X;

//dst & src must be uint32_t[32]. Note only 8 operations, to account for "128-bit" though neon really only does 64-bit at a time.
static inline void memcpy128neon(uint32_t * __restrict dst, uint32_t * __restrict src)
{
uint32x4_t *s1 = (uint32x4_t *) dst;
uint32x4_t *s2 = (uint32x4_t *) src;

*s1++ = *s2++;*s1++ = *s2++;*s1++ = *s2++;*s1++ = *s2++;*s1++ = *s2++;*s1++ = *s2++;*s1++ = *s2++;*s1++ = *s2++;
}

然后像这样调用...memcpy128neon(&X.x00,arr);

更新 16-10-2018如果找到这个允许 Union Casting 的宏...

#define UNION_CAST(x, destType) \
(((union {__typeof__(x) a; destType b;})x).b)

下面是一个使用自定义类型创建 1024 位指针的示例,该自定义类型基于 Arm 的 neon uint32x4_t vector ,用于具有 8 个索引的数组,但可以使用任何数据类型。这使得转换符合严格的别名。

uint32x4x8_t *pointer = (uint32x4x8_t *) UNION_CAST(originalpointer, uint32x4x8_t *);

最佳答案

不保证变量会按照声明的顺序放入内存。

我会用 union 双关自己。

#include <stdio.h>
#include <stdint.h>
#include <string.h>

#define SOMETHING (uint64_t *)0x12345676 // only
#define LITTLEENDIAN 1

typedef union
{
uint32_t u32[2];
uint64_t u64;
}data_64;

int main()
{
uint64_t *Bu64ptr = SOMETHING;

data_64 mydata[10];

//you can copy memory
memcpy(mydata, Bu64ptr, sizeof(mydata));

//or just loop
for(size_t index = 0; index < sizeof(mydata) / sizeof(mydata[0]); index++)
{
mydata[index].u64 = *Bu64ptr++;
}

for(size_t index = 0; index < sizeof(mydata) / sizeof(mydata[0]); index++)
{
printf("Lower word = %x, Upper word = %x\n", mydata[!LITTLEENDIAN], mydata[LITTLEENDIAN]);
}

return 0;
}

在相反的方向上它会以完全相同的方式工作

关于c - 从 uint32_t[16] 数组到 uint32_t 变量序列的 64 位副本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52212785/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com