mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Adds optimized SSSE3 functions for recovering.
This commit is contained in:
parent
6a00099863
commit
3dd6e50c4e
6 changed files with 1512 additions and 75 deletions
28
mktables.c
28
mktables.c
|
|
@ -294,6 +294,34 @@ int main(void)
|
|||
printf("};\n");
|
||||
printf("#endif\n\n");
|
||||
|
||||
printf("#if defined(__i386__) || defined(__x86_64__)\n");
|
||||
printf("/**\n");
|
||||
printf(" * PSHUFB tables for generic multiplication.\n");
|
||||
printf(" *\n");
|
||||
printf(" * Indexes are [MULTIPLER][LH].\n");
|
||||
printf(" * Where MULTIPLER is from 0 to 255, LH from 0 to 1.\n");
|
||||
printf(" */\n");
|
||||
printf("const unsigned char __attribute__((aligned(256))) gfmulpshufb[256][2][16] =\n");
|
||||
printf("{\n");
|
||||
for(i=0;i<256;++i) {
|
||||
printf("\t{\n");
|
||||
for(j=0;j<2;++j) {
|
||||
printf("\t\t{ ");
|
||||
for(k=0;k<16;++k) {
|
||||
v = gfmul(i, k);
|
||||
if (j == 1)
|
||||
v = gfmul(v, 16);
|
||||
printf("0x%02x", (unsigned)v);
|
||||
if (k != 15)
|
||||
printf(", ");
|
||||
}
|
||||
printf(" },\n");
|
||||
}
|
||||
printf("\t},\n");
|
||||
}
|
||||
printf("};\n");
|
||||
printf("#endif\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
327
raid.c
327
raid.c
|
|
@ -1228,7 +1228,7 @@ void raidPP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
asm volatile("movdqa %0,%%xmm4" : : "m" (vbuf[l][i]));
|
||||
|
||||
asm volatile("movdqa %xmm4,%xmm0");
|
||||
asm volatile("movdqa %%xmm4,%0" : "=m" (p0));
|
||||
asm volatile("movdqa %%xmm4,%0" : "=m" (p0[0]));
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
|
||||
asm volatile("movdqa %xmm4,%xmm5");
|
||||
|
|
@ -1268,7 +1268,7 @@ void raidPP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
|
||||
asm volatile("pxor %xmm4,%xmm0");
|
||||
asm volatile("pxor %xmm4,%xmm6");
|
||||
asm volatile("movdqa %%xmm6,%0" : "=m" (p0));
|
||||
asm volatile("movdqa %%xmm6,%0" : "=m" (p0[0]));
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
|
||||
asm volatile("movdqa %xmm4,%xmm5");
|
||||
|
|
@ -1542,8 +1542,8 @@ void raidHP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
/* last disk without the by two multiplication */
|
||||
asm volatile("movdqa %0,%%xmm4" : : "m" (vbuf[l][i]));
|
||||
|
||||
asm volatile("movdqa %%xmm4,%0" : "=m" (p0));
|
||||
asm volatile("movdqa %%xmm4,%0" : "=m" (q0));
|
||||
asm volatile("movdqa %%xmm4,%0" : "=m" (p0[0]));
|
||||
asm volatile("movdqa %%xmm4,%0" : "=m" (q0[0]));
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
|
||||
asm volatile("movdqa %xmm4,%xmm5");
|
||||
|
|
@ -1591,8 +1591,8 @@ void raidHP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
|
||||
asm volatile("pxor %xmm4,%xmm5");
|
||||
asm volatile("pxor %xmm4,%xmm6");
|
||||
asm volatile("movdqa %%xmm5,%0" : "=m" (p0));
|
||||
asm volatile("movdqa %%xmm6,%0" : "=m" (q0));
|
||||
asm volatile("movdqa %%xmm5,%0" : "=m" (p0[0]));
|
||||
asm volatile("movdqa %%xmm6,%0" : "=m" (q0[0]));
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
|
||||
asm volatile("movdqa %xmm4,%xmm5");
|
||||
|
|
@ -1933,9 +1933,9 @@ static inline void raid_delta_gen(unsigned level, const int* d, const int* c, un
|
|||
*
|
||||
* and solving we get:
|
||||
*
|
||||
* Dx = Pd (this one is easy :D)
|
||||
* Dx = Pd
|
||||
*/
|
||||
static void raid5_recov_data(const int* d, unsigned char** vbuf, unsigned data, unsigned size)
|
||||
static void raid5_recov1(const int* d, unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* pa;
|
||||
|
|
@ -1982,7 +1982,7 @@ static void raid5_recov_data(const int* d, unsigned char** vbuf, unsigned data,
|
|||
*
|
||||
* That are always satisfied for any 0<=d[0]<d[1]<255.
|
||||
*/
|
||||
static void raid6_recov_2data(const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
static void raid6_recov2(const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned char* p;
|
||||
|
|
@ -2100,21 +2100,31 @@ static inline void invert(unsigned char* M, unsigned char* V, unsigned n)
|
|||
*
|
||||
* Dx = A[c[0],d[0]]^-1 * Pd
|
||||
*/
|
||||
static void raid_recov_1data(const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
void raid_recov1_int8(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned char* p;
|
||||
unsigned char* pa;
|
||||
const unsigned char* T[1]; /* P factor to compute Dx */
|
||||
const unsigned char* T;
|
||||
unsigned char G;
|
||||
unsigned char V;
|
||||
|
||||
/* if it's RAID5 uses the dedicated and fasteT[ ][2]unction */
|
||||
(void)level; /* unused */
|
||||
|
||||
/* if it's RAID5 uses the dedicated and fastest function */
|
||||
if (c[0] == 0) {
|
||||
raid5_recov_data(d, vbuf, data, size);
|
||||
raid5_recov1(d, vbuf, data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
/* setup the coefficients matrix */
|
||||
G = A(c[0],d[0]);
|
||||
|
||||
/* invert it to solve the system of linear equations */
|
||||
V = inv(G);
|
||||
|
||||
/* get multiplication tables */
|
||||
T[0] = table( inv(A(c[0],d[0])) );
|
||||
T = table(V);
|
||||
|
||||
/* compute delta parity */
|
||||
raid_delta_gen(1, d, c, vbuf, data, zero, size);
|
||||
|
|
@ -2127,7 +2137,7 @@ static void raid_recov_1data(const int* d, const int* c, unsigned char** vbuf, u
|
|||
unsigned char Pd = p[i] ^ pa[i];
|
||||
|
||||
/* reconstruct */
|
||||
pa[i] = T[0][Pd];
|
||||
pa[i] = T[Pd];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2141,7 +2151,7 @@ static void raid_recov_1data(const int* d, const int* c, unsigned char** vbuf, u
|
|||
*
|
||||
* we solve inverting the coefficients matrix.
|
||||
*/
|
||||
static void raid_recov_2data(const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
void raid_recov2_int8(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* pa;
|
||||
|
|
@ -2153,9 +2163,11 @@ static void raid_recov_2data(const int* d, const int* c, unsigned char** vbuf, u
|
|||
unsigned char V[N*N];
|
||||
unsigned i, j;
|
||||
|
||||
(void)level; /* unused */
|
||||
|
||||
/* if it's RAID6 uses the dedicated and fasteT[ ][2]unction */
|
||||
if (c[0] == 0 && c[1] == 1) {
|
||||
raid6_recov_2data(d, c, vbuf, data, zero, size);
|
||||
raid6_recov2(d, c, vbuf, data, zero, size);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2208,8 +2220,7 @@ static void raid_recov_2data(const int* d, const int* c, unsigned char** vbuf, u
|
|||
* PD[0] = Pd, PD[1] = Qd, PD[2] = Rd, ...
|
||||
* D[0] = Dx, D[1] = Dy, D[2] = Dz, ...
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void raid_recov_data(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
void raid_recovX_int8(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
{
|
||||
unsigned char* p[RAID_PARITY_MAX];
|
||||
unsigned char* pa[RAID_PARITY_MAX];
|
||||
|
|
@ -2260,22 +2271,260 @@ static inline void raid_recov_data(unsigned level, const int* d, const int* c, u
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* RAID recovering for one disk SSSE3 implementation
|
||||
*/
|
||||
void raid_recov1_ssse3(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* pa;
|
||||
unsigned char G;
|
||||
unsigned char V;
|
||||
unsigned i;
|
||||
|
||||
(void)level; /* unused */
|
||||
|
||||
/* if it's RAID5 uses the dedicated and fastest function */
|
||||
if (c[0] == 0) {
|
||||
raid5_recov1(d, vbuf, data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
/* setup the coefficients matrix */
|
||||
G = A(c[0],d[0]);
|
||||
|
||||
/* invert it to solve the system of linear equations */
|
||||
V = inv(G);
|
||||
|
||||
/* compute delta parity */
|
||||
raid_delta_gen(1, d, c, vbuf, data, zero, size);
|
||||
|
||||
p = vbuf[data+c[0]];
|
||||
pa = vbuf[d[0]];
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
|
||||
asm volatile("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0]));
|
||||
asm volatile("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0]));
|
||||
|
||||
for(i=0;i<size;i+=16) {
|
||||
asm volatile("movdqa %0,%%xmm0" : : "m" (p[i]));
|
||||
asm volatile("movdqa %0,%%xmm1" : : "m" (pa[i]));
|
||||
asm volatile("movdqa %xmm4,%xmm2");
|
||||
asm volatile("movdqa %xmm5,%xmm3");
|
||||
asm volatile("pxor %xmm0,%xmm1");
|
||||
asm volatile("movdqa %xmm1,%xmm0");
|
||||
asm volatile("psraw $4,%xmm1");
|
||||
asm volatile("pand %xmm7,%xmm0");
|
||||
asm volatile("pand %xmm7,%xmm1");
|
||||
asm volatile("pshufb %xmm0,%xmm2");
|
||||
asm volatile("pshufb %xmm1,%xmm3");
|
||||
asm volatile("pxor %xmm3,%xmm2");
|
||||
asm volatile("movdqa %%xmm2,%0" : "=m" (pa[i]));
|
||||
}
|
||||
|
||||
asm volatile("sfence" : : : "memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* RAID recovering for two disks SSSE3 implementation
|
||||
*/
|
||||
void raid_recov2_ssse3(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
{
|
||||
const unsigned N = 2;
|
||||
unsigned char* p[N];
|
||||
unsigned char* pa[N];
|
||||
unsigned char G[N*N];
|
||||
unsigned char V[N*N];
|
||||
unsigned i, j;
|
||||
|
||||
(void)level; /* unused */
|
||||
|
||||
/* setup the coefficients matrix */
|
||||
for(i=0;i<N;++i) {
|
||||
for(j=0;j<N;++j) {
|
||||
G[i*N+j] = A(c[i],d[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* invert it to solve the system of linear equations */
|
||||
invert(G, V, N);
|
||||
|
||||
/* compute delta parity */
|
||||
raid_delta_gen(N, d, c, vbuf, data, zero, size);
|
||||
|
||||
for(i=0;i<N;++i) {
|
||||
p[i] = vbuf[data+c[i]];
|
||||
pa[i] = vbuf[d[i]];
|
||||
}
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
|
||||
|
||||
for(i=0;i<size;i+=16) {
|
||||
asm volatile("movdqa %0,%%xmm0" : : "m" (p[0][i]));
|
||||
asm volatile("movdqa %0,%%xmm2" : : "m" (pa[0][i]));
|
||||
asm volatile("movdqa %0,%%xmm1" : : "m" (p[1][i]));
|
||||
asm volatile("movdqa %0,%%xmm3" : : "m" (pa[1][i]));
|
||||
asm volatile("pxor %xmm2,%xmm0");
|
||||
asm volatile("pxor %xmm3,%xmm1");
|
||||
|
||||
asm volatile("pxor %xmm6,%xmm6");
|
||||
|
||||
asm volatile("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[0]][0][0]));
|
||||
asm volatile("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[0]][1][0]));
|
||||
asm volatile("movdqa %xmm0,%xmm4");
|
||||
asm volatile("movdqa %xmm0,%xmm5");
|
||||
asm volatile("psraw $4,%xmm5");
|
||||
asm volatile("pand %xmm7,%xmm4");
|
||||
asm volatile("pand %xmm7,%xmm5");
|
||||
asm volatile("pshufb %xmm4,%xmm2");
|
||||
asm volatile("pshufb %xmm5,%xmm3");
|
||||
asm volatile("pxor %xmm2,%xmm6");
|
||||
asm volatile("pxor %xmm3,%xmm6");
|
||||
|
||||
asm volatile("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[1]][0][0]));
|
||||
asm volatile("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[1]][1][0]));
|
||||
asm volatile("movdqa %xmm1,%xmm4");
|
||||
asm volatile("movdqa %xmm1,%xmm5");
|
||||
asm volatile("psraw $4,%xmm5");
|
||||
asm volatile("pand %xmm7,%xmm4");
|
||||
asm volatile("pand %xmm7,%xmm5");
|
||||
asm volatile("pshufb %xmm4,%xmm2");
|
||||
asm volatile("pshufb %xmm5,%xmm3");
|
||||
asm volatile("pxor %xmm2,%xmm6");
|
||||
asm volatile("pxor %xmm3,%xmm6");
|
||||
|
||||
asm volatile("movdqa %%xmm6,%0" : "=m" (pa[0][i]));
|
||||
|
||||
asm volatile("pxor %xmm6,%xmm6");
|
||||
|
||||
asm volatile("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[2]][0][0]));
|
||||
asm volatile("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[2]][1][0]));
|
||||
asm volatile("movdqa %xmm0,%xmm4");
|
||||
asm volatile("movdqa %xmm0,%xmm5");
|
||||
asm volatile("psraw $4,%xmm5");
|
||||
asm volatile("pand %xmm7,%xmm4");
|
||||
asm volatile("pand %xmm7,%xmm5");
|
||||
asm volatile("pshufb %xmm4,%xmm2");
|
||||
asm volatile("pshufb %xmm5,%xmm3");
|
||||
asm volatile("pxor %xmm2,%xmm6");
|
||||
asm volatile("pxor %xmm3,%xmm6");
|
||||
|
||||
asm volatile("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[3]][0][0]));
|
||||
asm volatile("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[3]][1][0]));
|
||||
asm volatile("movdqa %xmm1,%xmm4");
|
||||
asm volatile("movdqa %xmm1,%xmm5");
|
||||
asm volatile("psraw $4,%xmm5");
|
||||
asm volatile("pand %xmm7,%xmm4");
|
||||
asm volatile("pand %xmm7,%xmm5");
|
||||
asm volatile("pshufb %xmm4,%xmm2");
|
||||
asm volatile("pshufb %xmm5,%xmm3");
|
||||
asm volatile("pxor %xmm2,%xmm6");
|
||||
asm volatile("pxor %xmm3,%xmm6");
|
||||
|
||||
asm volatile("movdqa %%xmm6,%0" : "=m" (pa[1][i]));
|
||||
}
|
||||
|
||||
asm volatile("sfence" : : : "memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* RAID recovering SSSE3 implementation
|
||||
*/
|
||||
void raid_recovX_ssse3(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
{
|
||||
unsigned N = level;
|
||||
unsigned char* p[RAID_PARITY_MAX];
|
||||
unsigned char* pa[RAID_PARITY_MAX];
|
||||
unsigned char G[RAID_PARITY_MAX*RAID_PARITY_MAX];
|
||||
unsigned char V[RAID_PARITY_MAX*RAID_PARITY_MAX];
|
||||
unsigned i, j, k;
|
||||
|
||||
/* setup the coefficients matrix */
|
||||
for(i=0;i<N;++i) {
|
||||
for(j=0;j<N;++j) {
|
||||
G[i*N+j] = A(c[i],d[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* invert it to solve the system of linear equations */
|
||||
invert(G, V, N);
|
||||
|
||||
/* compute delta parity */
|
||||
raid_delta_gen(N, d, c, vbuf, data, zero, size);
|
||||
|
||||
for(i=0;i<N;++i) {
|
||||
p[i] = vbuf[data+c[i]];
|
||||
pa[i] = vbuf[d[i]];
|
||||
}
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
|
||||
|
||||
for(i=0;i<size;i+=16) {
|
||||
unsigned char PD[RAID_PARITY_MAX][16] __attribute__((aligned(16)));
|
||||
|
||||
/* delta */
|
||||
for(j=0;j<N;++j) {
|
||||
asm volatile("movdqa %0,%%xmm0" : : "m" (p[j][i]));
|
||||
asm volatile("movdqa %0,%%xmm1" : : "m" (pa[j][i]));
|
||||
asm volatile("pxor %xmm1,%xmm0");
|
||||
asm volatile("movdqa %%xmm0,%0" : "=m" (PD[j][0]));
|
||||
}
|
||||
|
||||
/* reconstruct */
|
||||
for(j=0;j<N;++j) {
|
||||
asm volatile("pxor %xmm0,%xmm0");
|
||||
asm volatile("pxor %xmm1,%xmm1");
|
||||
|
||||
for(k=0;k<N;++k) {
|
||||
unsigned char m = V[j*N+k];
|
||||
|
||||
asm volatile("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[m][0][0]));
|
||||
asm volatile("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[m][1][0]));
|
||||
asm volatile("movdqa %0,%%xmm4" : : "m" (PD[k][0]));
|
||||
asm volatile("movdqa %xmm4,%xmm5");
|
||||
asm volatile("psraw $4,%xmm5");
|
||||
asm volatile("pand %xmm7,%xmm4");
|
||||
asm volatile("pand %xmm7,%xmm5");
|
||||
asm volatile("pshufb %xmm4,%xmm2");
|
||||
asm volatile("pshufb %xmm5,%xmm3");
|
||||
asm volatile("pxor %xmm2,%xmm0");
|
||||
asm volatile("pxor %xmm3,%xmm1");
|
||||
|
||||
}
|
||||
|
||||
asm volatile("pxor %xmm1,%xmm0");
|
||||
asm volatile("movdqa %%xmm0,%0" : "=m" (pa[j][i]));
|
||||
}
|
||||
}
|
||||
|
||||
asm volatile("sfence" : : : "memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* internal forwarder */
|
||||
static void (*raid_recov1)(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
static void (*raid_recov2)(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
static void (*raid_recovX)(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
|
||||
void raid_recov(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
{
|
||||
switch (level) {
|
||||
case 1 :
|
||||
raid_recov_1data(d, c, vbuf, data, zero, size);
|
||||
raid_recov1(level, d, c, vbuf, data, zero, size);
|
||||
break;
|
||||
case 2 :
|
||||
raid_recov_2data(d, c, vbuf, data, zero, size);
|
||||
raid_recov2(level, d, c, vbuf, data, zero, size);
|
||||
break;
|
||||
case 3 :
|
||||
case 4 :
|
||||
case 5 :
|
||||
case 6 :
|
||||
/* note that this switch case ends with inlined */
|
||||
/* functions called with constant "level" */
|
||||
raid_recov_data(level, d, c, vbuf, data, zero, size);
|
||||
raid_recovX(level, d, c, vbuf, data, zero, size);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid raid recov level\n");
|
||||
|
|
@ -2301,6 +2550,10 @@ void raid_init(void)
|
|||
raid6_gen = raid6_int64;
|
||||
}
|
||||
|
||||
raid_recov1 = raid_recov1_int8;
|
||||
raid_recov2 = raid_recov2_int8;
|
||||
raid_recovX = raid_recovX_int8;
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_sse2()) {
|
||||
raid5_gen = raid5_sse2;
|
||||
|
|
@ -2315,7 +2568,7 @@ void raid_init(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
if (cpu_has_ssse3() && !cpu_has_slowpshufb()) {
|
||||
if (cpu_has_ssse3()) {
|
||||
#if defined(__x86_64__)
|
||||
raidTP_gen = raidTP_ssse3ext;
|
||||
raidQP_gen = raidQP_ssse3ext;
|
||||
|
|
@ -2327,6 +2580,9 @@ void raid_init(void)
|
|||
raidPP_gen = raidPP_ssse3;
|
||||
raidHP_gen = raidHP_ssse3;
|
||||
#endif
|
||||
raid_recov1 = raid_recov1_ssse3;
|
||||
raid_recov2 = raid_recov2_ssse3;
|
||||
raid_recovX = raid_recovX_ssse3;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -2343,6 +2599,9 @@ static struct raid_func {
|
|||
{ "int64", raid5_int64 },
|
||||
{ "int32", raid6_int32 },
|
||||
{ "int64", raid6_int64 },
|
||||
{ "int8", raid_recov1_int8 },
|
||||
{ "int8", raid_recov2_int8 },
|
||||
{ "int8", raid_recovX_int8 },
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
{ "sse2", raid5_sse2 },
|
||||
|
|
@ -2351,6 +2610,9 @@ static struct raid_func {
|
|||
{ "ssse3", raidQP_ssse3 },
|
||||
{ "ssse3", raidPP_ssse3 },
|
||||
{ "ssse3", raidHP_ssse3 },
|
||||
{ "ssse3", raid_recov1_ssse3 },
|
||||
{ "ssse3", raid_recov2_ssse3 },
|
||||
{ "ssse3", raid_recovX_ssse3 },
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
|
@ -2404,3 +2666,18 @@ const char* raidHP_tag(void)
|
|||
return raid_tag(raidHP_gen);
|
||||
}
|
||||
|
||||
const char* raid_recov1_tag(void)
|
||||
{
|
||||
return raid_tag(raid_recov1);
|
||||
}
|
||||
|
||||
const char* raid_recov2_tag(void)
|
||||
{
|
||||
return raid_tag(raid_recov2);
|
||||
}
|
||||
|
||||
const char* raid_recovX_tag(void)
|
||||
{
|
||||
return raid_tag(raid_recovX);
|
||||
}
|
||||
|
||||
|
|
|
|||
9
raid.h
9
raid.h
|
|
@ -77,6 +77,9 @@ const char* raidTP_tag(void);
|
|||
const char* raidQP_tag(void);
|
||||
const char* raidPP_tag(void);
|
||||
const char* raidHP_tag(void);
|
||||
const char* raid_recov1_tag(void);
|
||||
const char* raid_recov2_tag(void);
|
||||
const char* raid_recovX_tag(void);
|
||||
|
||||
/**
|
||||
* Specialized parity computation.
|
||||
|
|
@ -101,6 +104,12 @@ void raidPP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
|||
void raidHP_int8(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidHP_ssse3(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidHP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raid_recov1_int8(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
void raid_recov2_int8(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
void raid_recovX_int8(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
void raid_recov1_ssse3(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
void raid_recov2_ssse3(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
void raid_recovX_ssse3(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
86
selftest.c
86
selftest.c
|
|
@ -67,7 +67,7 @@ static void combotest(void)
|
|||
/* all parities */
|
||||
for(r=1;r<=LEV_MAX;++r) {
|
||||
/* count combination (r of LEV_MAX) parities */
|
||||
count = 0;
|
||||
count = 0;
|
||||
combination_first(r, LEV_MAX, p);
|
||||
do {
|
||||
++count;
|
||||
|
|
@ -97,6 +97,8 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
unsigned i;
|
||||
unsigned j;
|
||||
unsigned r;
|
||||
void (*map[LEV_MAX][4])(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
unsigned mac[LEV_MAX];
|
||||
|
||||
buffermax = diskmax + LEV_MAX * 2 + 2;
|
||||
|
||||
|
|
@ -121,6 +123,33 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
data[i][j] = rand();
|
||||
}
|
||||
|
||||
/* setup recov functions */
|
||||
for(i=0;i<LEV_MAX;++i) {
|
||||
mac[i] = 0;
|
||||
if (i == 0) {
|
||||
map[i][mac[i]++] = raid_recov1_int8;
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
map[i][mac[i]++] = raid_recov1_ssse3;
|
||||
}
|
||||
#endif
|
||||
} else if (i == 1) {
|
||||
map[i][mac[i]++] = raid_recov2_int8;
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
map[i][mac[i]++] = raid_recov2_ssse3;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
map[i][mac[i]++] = raid_recovX_int8;
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
map[i][mac[i]++] = raid_recovX_ssse3;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_gen(LEV_MAX, buffer, diskmax, block_size);
|
||||
|
||||
|
|
@ -130,40 +159,41 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
|
||||
/* all parity levels */
|
||||
for(r=1;r<=LEV_MAX;++r) {
|
||||
|
||||
/* all combinations (r of diskmax) disks */
|
||||
combination_first(r, diskmax, d);
|
||||
do {
|
||||
|
||||
/* all combinations (r of LEV_MAX) parities */
|
||||
combination_first(r, LEV_MAX, p);
|
||||
do {
|
||||
/* set */
|
||||
for(i=0;i<r;++i) {
|
||||
/* remove the missing data */
|
||||
data_save[i] = data[d[i]];
|
||||
data[d[i]] = test[i];
|
||||
/* set the parity to use */
|
||||
parity[p[i]] = parity_save[p[i]];
|
||||
}
|
||||
|
||||
/* recover */
|
||||
raid_recov(r, d, p, buffer, diskmax, zero, block_size);
|
||||
|
||||
/* check */
|
||||
for(i=0;i<r;++i) {
|
||||
if (memcmp(test[i], data_save[i], block_size) != 0) {
|
||||
fprintf(stderr, "Failed RECOV test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* for each recover function */
|
||||
for(j=0;j<mac[r-1];++j) {
|
||||
/* set */
|
||||
for(i=0;i<r;++i) {
|
||||
/* remove the missing data */
|
||||
data_save[i] = data[d[i]];
|
||||
data[d[i]] = test[i];
|
||||
/* set the parity to use */
|
||||
parity[p[i]] = parity_save[p[i]];
|
||||
}
|
||||
}
|
||||
|
||||
/* restore */
|
||||
for(i=0;i<r;++i) {
|
||||
/* restore the data */
|
||||
data[d[i]] = data_save[i];
|
||||
/* restore the parity */
|
||||
parity[p[i]] = waste;
|
||||
/* recover */
|
||||
map[r-1][0](r, d, p, buffer, diskmax, zero, block_size);
|
||||
|
||||
/* check */
|
||||
for(i=0;i<r;++i) {
|
||||
if (memcmp(test[i], data_save[i], block_size) != 0) {
|
||||
fprintf(stderr, "Failed RECOV test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* restore */
|
||||
for(i=0;i<r;++i) {
|
||||
/* restore the data */
|
||||
data[d[i]] = data_save[i];
|
||||
/* restore the parity */
|
||||
parity[p[i]] = waste;
|
||||
}
|
||||
}
|
||||
} while (combination_next(r, LEV_MAX, p));
|
||||
} while (combination_next(r, diskmax, d));
|
||||
|
|
@ -369,5 +399,5 @@ void selftest()
|
|||
crc32ctest();
|
||||
combotest();
|
||||
gentest(32, 256);
|
||||
recovtest(16, 256);
|
||||
recovtest(12, 256);
|
||||
}
|
||||
|
|
|
|||
101
speed.c
101
speed.c
|
|
@ -507,82 +507,141 @@ void speed(void)
|
|||
/* recover table */
|
||||
printf("RAID functions used for recovering with 'fix':\n");
|
||||
printf("%8s", "");
|
||||
printf("%8s", "");
|
||||
printf("%8s", "best");
|
||||
printf("%8s", "int8");
|
||||
printf("%8s", "ssse3");
|
||||
printf("\n");
|
||||
|
||||
printf("%8s", "raid5");
|
||||
printf("%8s", "");
|
||||
printf("%8s", "recov1");
|
||||
printf("%8s", raid_recov1_tag());
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recov(1, d, e, buffer, diskmax, zero, block_size);
|
||||
/* +1 to avoid RAID5 optimized case */
|
||||
raid_recov1_int8(1, d, e + 1, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
/* +1 to avoid RAID5 optimized case */
|
||||
raid_recov1_ssse3(1, d, e + 1, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
printf("\n");
|
||||
|
||||
printf("%8s", "raid6");
|
||||
printf("%8s", "");
|
||||
printf("%8s", "recov2");
|
||||
printf("%8s", raid_recov2_tag());
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recov(2, d, e, buffer, diskmax, zero, block_size);
|
||||
/* +1 to avoid RAID6 optimized case */
|
||||
raid_recov2_int8(2, d, e + 1, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
/* +1 to avoid RAID6 optimized case */
|
||||
raid_recov2_ssse3(2, d, e + 1, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
printf("\n");
|
||||
|
||||
printf("%8s", "raidTP");
|
||||
printf("%8s", "");
|
||||
printf("%8s", "recov3");
|
||||
printf("%8s", raid_recovX_tag());
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recov(3, d, e, buffer, diskmax, zero, block_size);
|
||||
raid_recovX_int8(3, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recovX_ssse3(3, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
printf("\n");
|
||||
|
||||
printf("%8s", "raidQP");
|
||||
printf("%8s", "");
|
||||
printf("%8s", "recov4");
|
||||
printf("%8s", raid_recovX_tag());
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recov(4, d, e, buffer, diskmax, zero, block_size);
|
||||
raid_recovX_int8(4, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recovX_ssse3(4, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
printf("\n");
|
||||
|
||||
printf("%8s", "raidPP");
|
||||
printf("%8s", "");
|
||||
printf("%8s", "recov5");
|
||||
printf("%8s", raid_recovX_tag());
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recov(5, d, e, buffer, diskmax, zero, block_size);
|
||||
raid_recovX_int8(5, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recovX_ssse3(5, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
printf("\n");
|
||||
|
||||
printf("%8s", "raidHP");
|
||||
printf("%8s", "");
|
||||
printf("%8s", "recov6");
|
||||
printf("%8s", raid_recovX_tag());
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recov(6, d, e, buffer, diskmax, zero, block_size);
|
||||
raid_recovX_int8(6, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
for(j=0;j<diskmax;++j) {
|
||||
raid_recovX_ssse3(6, d, e, buffer, diskmax, zero, block_size);
|
||||
}
|
||||
} SPEED_STOP
|
||||
|
||||
|
|
@ -590,9 +649,7 @@ void speed(void)
|
|||
printf("\n");
|
||||
printf("\n");
|
||||
|
||||
printf("If the 'best' expectations are wrong, please report it in the SnapRAID forum\n");
|
||||
|
||||
printf("\n");
|
||||
printf("If the 'best' expectations are wrong, please report it in the SnapRAID forum\n\n");
|
||||
|
||||
free(buffer_alloc);
|
||||
free(buffer);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue