Refactors vector operations.

This commit is contained in:
Andrea Mazzoleni 2014-01-02 17:51:50 +01:00
parent 29b411e3fe
commit cae803bdfb
10 changed files with 75 additions and 76 deletions

View file

@ -488,7 +488,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc);
if (!state->opt.skip_self)
mtest_vector(buffer, buffermax, state->block_size);
mtest_vector(buffermax, state->block_size, buffer);
/* fill up the zero buffer */
memset(buffer[buffermax-1], 0, state->block_size);

View file

@ -34,41 +34,53 @@ void *raid_malloc_align(size_t size, void **freeptr)
return ptr;
}
void **raid_malloc_vector(size_t reverse, size_t count, size_t size, void **freeptr)
void **raid_malloc_vector(int nd, int n, size_t size, void **freeptr)
{
void **v;
unsigned char *va;
size_t i;
int i;
assert(reverse <= count);
v = malloc(count * sizeof(void *));
v = malloc(n * sizeof(void *));
if (!v)
return 0;
va = raid_malloc_align(count * (size + RAID_MALLOC_DISPLACEMENT), freeptr);
va = raid_malloc_align(n * (size + RAID_MALLOC_DISPLACEMENT), freeptr);
if (!va) {
free(v);
return 0;
}
for (i = 0; i < count; ++i)
v[i] = va + i * (size + RAID_MALLOC_DISPLACEMENT);
for (i = 0; i < n; ++i) {
v[i] = va;
va += size + RAID_MALLOC_DISPLACEMENT;
}
/* reverse order for the initial ones */
for (i = 0; i < reverse/2; ++i) {
/* reverse order of the data blocks */
/* because they are usually accessed from the last one */
for (i = 0; i < nd/2; ++i) {
void *ptr = v[i];
v[i] = v[reverse - 1 - i];
v[reverse - 1 - i] = ptr;
v[i] = v[nd - 1 - i];
v[nd - 1 - i] = ptr;
}
return v;
}
int raid_mtest_vector(void **vv, size_t count, size_t size)
void raid_mrand_vector(int n, size_t size, void **vv)
{
unsigned char **v = (unsigned char **)vv;
size_t i;
int i;
size_t j;
for (i = 0; i < n; ++i)
for (j = 0; j < size; ++j)
v[i][j] = rand();
}
int raid_mtest_vector(int n, size_t size, void **vv)
{
unsigned char **v = (unsigned char **)vv;
int i;
size_t j;
unsigned k;
unsigned char d;
@ -76,7 +88,7 @@ int raid_mtest_vector(void **vv, size_t count, size_t size)
/* fill with 0 */
d = 0;
for (i = 0; i < count; ++i)
for (i = 0; i < n; ++i)
for (j = 0; j < size; ++j)
v[i][j] = d;
@ -86,7 +98,7 @@ int raid_mtest_vector(void **vv, size_t count, size_t size)
d = k;
/* forward fill */
for (i = 0; i < count; ++i) {
for (i = 0; i < n; ++i) {
for (j = 0; j < size; ++j) {
if (v[i][j] != p)
return -1;
@ -97,7 +109,7 @@ int raid_mtest_vector(void **vv, size_t count, size_t size)
p = d;
d = ~p;
/* backward fill with complement */
for (i = 0; i < count; ++i) {
for (i = 0; i < n; ++i) {
for (j = size; j > 0; --j) {
if (v[i][j-1] != p)
return -1;
@ -109,14 +121,3 @@ int raid_mtest_vector(void **vv, size_t count, size_t size)
return 0;
}
void raid_mrand_vector(void **vv, size_t count, size_t size)
{
unsigned char **v = (unsigned char **)vv;
size_t i;
size_t j;
for (i = 0; i < count; ++i)
for (j = 0; j < size; ++j)
v[i][j] = rand();
}

View file

@ -28,26 +28,27 @@
*
* When allocating a sequence of blocks with a size of power of 2,
* there is the risk that the start of each block is mapped into the same
* cache line, resulting in cache collisions if you access all the blocks
* in parallel, from the start to the end.
* cache line or prefetching prediction, resulting in collisions if you
* access all the blocks in parallel, from the start to the end.
*
* The selected value was choosen empirically with some speed tests
* with 8/12/16/20/24 data buffers of 256 KB.
*
* With displacement:
* (8 buffers of 256 KB, icore5, 32 bits):
* These are the results with no displacement:
*
* sse2
* par1 21936 [MB/s]
* par2 11902 [MB/s]
* parz 5838 [MB/s]
* sse2
* par1 15368 [MB/s]
* par2 6814 [MB/s]
* parz 3033 [MB/s]
*
* Without displacement:
* These are the results with displacement resulting in improvments
* in the order of 20% or more:
*
* sse2
* par1 21936 [MB/s]
* par2 11902 [MB/s]
* parz 5838 [MB/s]
*
* sse2
* par1 15368 [MB/s]
* par2 6814 [MB/s]
* parz 3033 [MB/s]
*/
#define RAID_MALLOC_DISPLACEMENT (7*256)
@ -58,22 +59,22 @@ void *raid_malloc_align(size_t size, void **freeptr);
/**
* Aligned vector allocation.
* Returns a vector of "count" pointers, each one pointing to a block of the
* specified "size".
* The first "reverse" pointers are put in reverse memory offset order.
* Returns a vector of ::n pointers, each one pointing to a block of
* the specified ::size.
* The first ::nd elements are reversed in order.
*/
void **raid_malloc_vector(size_t reverse, size_t count, size_t size, void **freeptr);
void **raid_malloc_vector(int nd, int n, size_t size, void **freeptr);
/**
* Fills the memory vector with random data.
*/
void raid_mrand_vector(int n, size_t size, void **vv);
/**
* Tests the memory vector for RAM problems.
* If a problem is found, it crashes.
*/
int raid_mtest_vector(void **vv, size_t count, size_t size);
/**
* Fills the memory vector with random data.
*/
void raid_mrand_vector(void **vv, size_t count, size_t size);
int raid_mtest_vector(int n, size_t size, void **vv);
#endif

View file

@ -228,7 +228,7 @@ int raid_selftest(void)
/* test parity generation */
ret = raid_test_par(nd, np, size, v, ref);
if (ret != 0)
return ret;
goto bail;
/* test recovering with full broken data disks */
for (i = 0; i < np; ++i)

View file

@ -148,7 +148,7 @@ int raid_test_rec(int mode, int nd, size_t size)
waste = v[nv-1];
/* fill data disk with random */
raid_mrand_vector(v, nd, size);
raid_mrand_vector(nd, size, v);
/* setup recov functions */
for (i = 0; i < np; ++i) {
@ -253,7 +253,7 @@ int raid_test_par(int mode, int nd, size_t size)
return -1;
/* fill with random */
raid_mrand_vector(v, nv, size);
raid_mrand_vector(nv, size, v);
/* compute the parity */
raid_par_ref(nd, np, size, v);

View file

@ -69,7 +69,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc);
if (!state->opt.skip_self)
mtest_vector(buffer, buffermax, state->block_size);
mtest_vector(buffermax, state->block_size, buffer);
error = 0;
silent_error = 0;

View file

@ -81,7 +81,6 @@ void speed(void)
void *v_alloc;
void **v;
/* we need disk + 1 for each parity buffers + 1 zero v */
nv = nd + RAID_PARITY_MAX + 1;
v = malloc_nofail_vector_align(nd, nv, size, &v_alloc);

2
sync.c
View file

@ -76,7 +76,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc);
if (!state->opt.skip_self)
mtest_vector(buffer, buffermax, state->block_size);
mtest_vector(buffermax, state->block_size, buffer);
error = 0;
silent_error = 0;

18
util.c
View file

@ -1384,11 +1384,11 @@ void* malloc_nofail_align(size_t size, void** freeptr)
return ptr;
}
void** malloc_nofail_vector_align(size_t reverse, size_t count, size_t size, void** freeptr)
void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr)
{
void* ptr;
ptr = raid_malloc_vector(reverse, count, size, freeptr);
ptr = raid_malloc_vector(nd, n, size, freeptr);
if (!ptr) {
/* don't use printf to avoid any possible extra allocation */
@ -1401,20 +1401,20 @@ void** malloc_nofail_vector_align(size_t reverse, size_t count, size_t size, voi
return ptr;
}
void mtest_vector(void** vv, size_t count, size_t size)
void mrand_vector(int n , size_t size, void** vv)
{
if (raid_mtest_vector(vv, count, size) != 0) {
raid_mrand_vector(n, size, vv);
}
void mtest_vector(int n , size_t size, void** vv)
{
if (raid_mtest_vector(n, size, vv) != 0) {
fprintf(stderr, "DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
fprintf(stderr, "Try running some memory test like http://www.memtest86.com/\n");
exit(EXIT_FAILURE);
}
}
void mrand_vector(void** vv, size_t count, size_t size)
{
raid_mrand_vector(vv, count, size);
}
/****************************************************************************/
/* byte operations */

16
util.h
View file

@ -466,22 +466,20 @@ void* malloc_nofail_align(size_t size, void** freeptr);
/**
* Safe aligned vector allocation.
* Returns a vector of "count" pointers, each one pointing to a block of the specified "size".
* The first "reverse" pointers are put in reverse memory offset order.
* If no memory is available, it aborts.
*/
void** malloc_nofail_vector_align(size_t reverse, size_t count, size_t size, void** freeptr);
void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr);
/**
* Fills the memory vector with random data.
*/
void mrand_vector(int n, size_t size, void** vv);
/**
* Tests the memory vector for RAM problems.
* If a problem is found, it crashes.
*/
void mtest_vector(void** vv, size_t count, size_t size);
/**
* Fills the memory vector with random data.
*/
void mrand_vector(void** vv, size_t count, size_t size);
void mtest_vector(int n, size_t size, void** vv);
/**
* Safe strdup.