簡體   English   中英

從uint32_t [16]數組復制到uint32_t變量序列的64位

[英]64-bit copy from uint32_t[16] array to sequence of uint32_t variables

我已經能夠在相等大小的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

我結束了使用結構,然后使用了基於霓虹燈的操作。 使用32位代碼和memcpy,性能比原始性能提高20%。 我還能夠擴展技術來添加和保存salsa20 / 8使用的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如果找到了允許聯合鑄造的宏...

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

這是使用基於Arm的neon uint32x4_t向量的自定義類型為具有8個索引的數組創建自定義類型來創建1024位指針的示例,但是可以使用任何數據類型。 這使轉換符合嚴格的別名。

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

無法保證將變量按照聲明中的順序放置在內存中。

我自己會用工會修剪。

#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;
}

它將在相反的方向完全相同地工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM