Working with big float data in C - c

I want to do some calculation with some matrices whose size is 2048*2048, for example.But the simulator stop working and it does not simulate the code. I understood that the problem is about the size and type of variable. For example, I run a simple code, which is written below, to check whether I am right or not. I should print 1 after declaring variable A. But it does not work.
Please note that I use Codeblocks. WFM is a function to write a float matrix in a text file and it works properly because I check that before with other matrices.
int main()
{
float A[2048][2048];
printf("1");
float *AP = &(A[0][0]);
const char *File_Name = "example.txt";
int counter = 0;
for(int i = 0; i < 2048; i++)
for(int j = 0; j < 2048; j++)
{
A[i][j] = counter;
++counter;
}
WFM(AP, 2048, 2048, File_Name , ' ');
return 0;
}
Any help and suggestion to deal with this problem and larger matrices is appreciate it.
Thanks

float A[2048][2048];
which requires approx. 2K * 2K * 8 = 32M of stack memory. But typically the stack size of the process if far less than that. Please allocate it dynamically using alloc family.

float A[2048][2048];
This may be too large for a local array, you should allocate memory dynamically by function such as malloc. For example, you could do this:
float *A = malloc(2048*2048*sizeof(float));
if (A == 0)
{
perror("malloc");
exit(1);
}
float *AP = A;
int counter = 0;
for(int i = 0; i < 2048; i++)
for(int j = 0; j < 2048; j++)
{
*(A + 2048*i + j) = counter;
++counter;
}
And when you does not need A anymore, you can free it by free(A);.
Helpful links about efficiency pitfalls of large arrays with power-of-2 size (offered by #LưuVĩnhPhúc):
Why is transposing a matrix of 512x512 much slower than transposing a matrix of 513x513?
Why is my program slow when looping over exactly 8192 elements?
Matrix multiplication: Small difference in matrix size, large difference in timings

Related

Saving 2D array to array

I am searching for solution in this problem. We have to program a program which can add/multiple unknown amount of matrix. Which means multiplication don't have to be at first position, but you have to do it first due to operand precedence. I have a idea of saving all matrix to an array. But I don't know how to save a matrix(2D array) to an array. We are programming in C. Anyone know a solution or a better solution? Thanks.
I would probably create a struct representing a matrix, something like: (i use int but it will work with doubles too you just need to change every int, apart from n, to double)
typedef struct m{
//stores the size of the matrix (assuming they are square matrices)
//otherwise you can just save the same n for everyone if they have the same size
int n;
int **map;
}matrix;
and then a pointer being an array of those structs, something like the following: (note that i omitted the checks that ensures the allocations will work, you'll need to write them) i use calloc because i like it more since it initializes all the positions to 0 but malloc will work too
// if you already know how many matrices you'll have
int number = get_matrix_number();
matrix *matrices = calloc(number, sizeof(matrix));
// otherwise
int numer = 1;
matrix *matrices = calloc(number, sizeof(matrix));
matrices[number - 1].n = get_matrix_dimension();
// then every time you need to add another matrix
number++;
matrices = realloc(number * sizeof(matrix));
matrices[number - 1].n = get_matrix_dimension();
After that to create the actual matrices you could do:
for (int i = 0; i < number; i++){
matrices[i].map = calloc(matrices[i].n, sizeof(int));
for (int j = 0; j < matrices[i].n; j++){
matrices[i].map[j] = calloc(matrices[i].n, sizeof(int));
}
}
After all of that to access, let's say, the position (3,5) in the 4th matrix you'll just need to do
int value = matrices[4].map[3][5];
I didn't test it (just wrote it as i think i would've) but i think it should work.
As i said you'll need to add the checks for the mallocs and the frees but i think it's easier to understand than straight triple pointers, especially if you don't have much experience in C (but you have to write more code since you need to create the struct).
The nice part is that this will work for matrices of different size and for non square matrices (provided you don't store just "n" but "n" and "m" to remember how many columns and rows each matrix has).
You could also make the allocation faster by allocating more than what you need when calling realloc (E.G. number * 2) so that you don't need to realloc every time but i think you'll need another variable to store how many free spaces you still have (never done it so this is just what i studied as theory hence i prefeared to do it this way since i'm pretty sure it will work).
P.S. There could be some errors here and there, i wrote it pretty fast without checking too carefully.
Although your question is still confusing, for that part where you want to save a 2D array to 1D array, the following code can help you ..
int n = 10;
int array2D[n][n];
int yourArray[n*n];
int i,j,k=0;
for(i = 0; i<n; i++){
for(j = 0; j<n ;j++){
yourArray[k++] = array2D[i][j];
}
}
You need 3D array for this. Something like double *** arrayOfMatrices.
I think that the simplest thing to do, if you want to work with matrices of different shapes, is to declare a struct that holds a pointer to double, which should simulate a 1d array, and the number of rows and columns of the matrix. The main code can declare a pointer to a matrix struct, and this simulates an array of matrices.
When you add a matrix, which I take to be a VLA so that different matrix shapes can easily be handled, the VLA is stored in the 1d simulated array.
Storing the matrix information in a struct this way also makes it easy to verify that matrix operations are defined for the matrices in question (e.g., matrix addition is only defined for matrices of the same shape).
Here is a simple example of how this idea could be implemented. The program defines 3 VLAs and adds them to a list of Matrix structs called matrices. Then the matrices are displayed by reading them from matrices.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
double *array;
size_t rows;
size_t cols;
} Matrix;
Matrix * add_matrix(size_t rs, size_t cs, double arr[rs][cs], Matrix *mx, size_t *n);
void show_matrix(Matrix mx);
int main(void)
{
Matrix *matrices = NULL;
size_t num_matrices = 0;
double m1[2][2] = {
{ 1, 2 },
{ 3, 4 }
};
double m2[2][3] = {
{ 1, 0, 0 },
{ 0, 1, 0 }
};
double m3[3][2] = {
{ 5, 1 },
{ 1, 0 },
{ 0, 0 }
};
matrices = add_matrix(2, 2, m1, matrices, &num_matrices);
matrices = add_matrix(2, 3, m2, matrices, &num_matrices);
matrices = add_matrix(3, 2, m3, matrices, &num_matrices);
show_matrix(matrices[0]);
show_matrix(matrices[1]);
show_matrix(matrices[2]);
/* Free allocated memory */
for (size_t i = 0; i < num_matrices; i++) {
free(matrices[i].array);
}
free(matrices);
return 0;
}
Matrix * add_matrix(size_t rs, size_t cs, double arr[rs][cs], Matrix *mx, size_t *n)
{
Matrix *temp = realloc(mx, sizeof(*temp) * (*n + 1));
if (temp == NULL) {
fprintf(stderr, "Allocation error\n");
exit(EXIT_FAILURE);
}
double *arr_1d = malloc(sizeof(*arr_1d) * rs * cs);
if (arr_1d == NULL) {
fprintf(stderr, "Allocation error\n");
exit(EXIT_FAILURE);
}
/* Store 2d VLA in arr_1d */
for (size_t i = 0; i < rs; i++)
for (size_t j = 0; j < cs; j++)
arr_1d[i * cs + j] = arr[i][j];
temp[*n].array = arr_1d;
temp[*n].rows = rs;
temp[*n].cols = cs;
++*n;
return temp;
}
void show_matrix(Matrix mx)
{
size_t rs = mx.rows;
size_t cs = mx.cols;
size_t i, j;
for (i = 0; i < rs; i++) {
for (j = 0; j < cs; j++)
printf("%5.2f", mx.array[i * cs + j]);
putchar('\n');
}
putchar('\n');
}
Output is:
1.00 2.00
3.00 4.00
1.00 0.00 0.00
0.00 1.00 0.00
5.00 1.00
1.00 0.00
0.00 0.00

Using memcpy for two dimensional dynamic array?

I am able to declare in a good way two matrices A and B.
But, when using the memcpy (to copy B from A), B gives me arrays of 0s.
How can I do? Is my code correct for using memcpy?
int r = 10, c = 10, i, j;
int (*MatrixA)[r];
MatrixA=malloc(c * sizeof(*MatrixA));
int (*MatrixB)[r];
MatrixB=malloc(c * sizeof(*MatrixB));
memcpy(MatrixB,MatrixA,c * sizeof(MatrixA));
for(i=1;i<r+1;i++)
{
for (j = 1; j < c+1; j++)
{
MatrixA[i][j]=j;
printf("A[%d][%d]= %d\t",i,j,MatrixA[i][j]);
}
printf("\n");
}
printf("\n");printf("\n");printf("\n");printf("\n");printf("\n");
for(i=1;i<r+1;i++)
{
for (j = 1; j < c+1; j++)
{
printf("B[%d][%d]= %d\t",i,j,MatrixB[i][j]);
}
printf("\n");
}
You copied contents before initializing MatrixA .And also you access index out of bound (r+1 evaluates 11 which is out of bound) causing UB. Do this instead -
for(i=0;i<r;i++) // i starts from 0
{
for (j =0; j < c; j++) // j from 0
{
MatrixA[i][j]=j;
printf("A[%d][%d]= %d\t",i,j,MatrixA[i][j]);
}
printf("\n");
}
memcpy(MatrixB,MatrixA,c * sizeof(*MatrixA)); // copy after setting MatrixA
for(i=0;i<r;i++) // similarly indexing starts with 0
{
for (j =0; j < c; j++)
{
printf("B[%d][%d]= %d\t",i,j,MatrixB[i][j]);
}
printf("\n");
}
Is my code correct for using memcpy?
No, your code is wrong, but that's less of a memcpy problem. You're simply doing C arrays wrong.
int r = 10, c = 10, i, j;
int (*MatrixA)[r];
MatrixA=malloc(c * sizeof(*MatrixA));
Ok, MatrixA is now a pointer to a 10-element array of integers right? So the compiler reserves memory for ten ints; however, in the malloc line, you overwrite that with a pointer to a memory region of ten times the size of a single integer. A code analysis tool will tell you that you've built a memory leak.
These mistakes continue throughout your code; you will have to understand the difference between statically allocated C arrays and dynamic allocation using malloc.

How do you break an array in to little arrays of a fixed size? (in C)

I was trying to do an exercise in Hacker Rank but found that my code(which is below) is too linear. To make it better I want to know if it is possible to break an array in to little arrays of a fixed size to complete this exercise.
The Exersise on HackerRank
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int N, M, Y, X;
scanf("%d %d %d %d", &N, &M, &Y, &X);
int max = 0;
int total = 0;
int data[N][M];
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
scanf("%d",&(data[i][j]));
}
}
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
total = 0;
for(int l = 0; (l < Y) && (i + Y) <= N; l++)
{
for(int k = 0; (k < X) && (j + X <= M); k++)
{
total += data[i+l][j+k];
}
if(total > max)
max = total;
}
}
}
printf("%d",max);
return 0;
}
While "breaking" it into pieces implies that we'd be moving things around in memory, you may be able to "view" the array in such a way that is equivalent.
In a very real sense the name of the array is simply a pointer to the first element. When you dereference an element of the array an array mapping function is used to perform pointer arithmetic so that the correct element can be located. This is necessary because C arrays do not natively have any pointer information within them to identify elements.
The nature of how arrays are stored, however, can be leveraged by you to treat the data as arbitrary arrays of whatever size you'd like. For example, if we had:
int integers[] = {1,2,3,4,5,6,7,8,9,10};
you could view this as a single array:
for(i=0;i!=10;i++){ printf("%d\n", integers[i]); }
But starting with the above array you could also do this:
int *iArray1, *iArray2;
iArray1 = integers;
iArray2 = integers + (5 * sizeof(int));
for(i=0;i!=5;i++){ printf("%d - %d\n", iArray1[i], iArray2[i]);}
In this way we are choosing to view the data as two 5 term arrays.
The problem is not in the linear solution. The main problem is in your algorithm complexity. As it's written it's O(N^4). Also I think your solution is not correct since:
The ceulluar tower can cover a regtangular area of Y rows and X columns.
It does not mean exactly Y rows and X columns IMHO you could find a solution where the are dimension is less than X, Y.
The problems like that are solvable in reasonable time using dynamic programming. Try to optimize your program using dynamic programming to O(N^2).

Saving multidimensional arrays in C

I have saved multidimensional arrays in Matlab before (e.g. an array A that has size 100x100x100) using a .mat file and that worked out very nicely.
What is the best way to save such multidimensional arrays in C? The only way I can think of is to store it as a 2D array (e.g. convert a KxNxM array to a KNxM array) and be careful in remembering how it was saved.
What is also desired is to save it in a way that can be opened later in Matlab for post-processing/plotting.
C does 3D arrays just fine:
double data[D0][D1][D2];
...
data[i][j][k] = ...;
although for very large arrays such as in your example, you would want to allocate the arrays dynamically instead of declaring them as auto variables such as above, since the space for auto variables (usually the stack, but not always) may be very limited.
Assuming all your dimensions are known at compile time, you could do something like:
#include <stdlib.h>
...
#define DO 100
#define D1 100
#define D2 100
...
double (*data)[D1][D2] = malloc(sizeof *data * D0);
if (data)
{
...
data[i][j][k] = ...;
...
free(data);
}
This will allocate a D0xD1xD2 array from the heap, and you can access it like any regular 3D array.
If your dimensions are not known until run time, but you're working with a C99 compiler or a C2011 compiler that supports variable-length arrays, you can do something like this:
#include <stdlib.h>
...
size_t d0, d1, d2;
d0 = ...;
d1 = ...;
d2 = ...;
...
double (*data)[d1][d2] = malloc(sizeof *data * d0);
if (data)
{
// same as above
}
If your dimensions are not known until runtime and you're working with a compiler that does not support variable-length arrays (C89 or earlier, or a C2011 compiler without VLA support), you'll need to take a different approach.
If the memory needs to be allocated contiguously, then you'll need to do something like the following:
size_t d0, d1, d2;
d0 = ...;
d1 = ...;
d2 = ...;
...
double *data = malloc(sizeof *data * d0 * d1 * d2);
if (data)
{
...
data[i * d0 * d1 + j * d1 + k] = ...;
...
free(data);
}
Note that you have to map your i, j, and k indices to a single index value.
If the memory doesn't need to be contiguous, you can do a piecemeal allocation like so:
double ***data;
...
data = malloc(d0 * sizeof *data);
if (data)
{
size_t i;
for (i = 0; i < d0; i++)
{
data[i] = malloc(d1 * sizeof *data[i]);
if (data[i])
{
size_t j;
for (j = 0; j < d1; j++)
{
data[i][j] = malloc(d2 * sizeof *data[i][j]);
if (data[i][j])
{
size_t k;
for (k = 0; k < d2; k++)
{
data[i][j][k] = initial_value();
}
}
}
}
}
}
and deallocate it as
for (i = 0; i < d0; i++)
{
for (j = 0; j < d1; j++)
{
free(data[i][j]);
}
free(data[i]);
}
free(data);
This is not recommended practice, btw; even though it allows you to index data as though it were a 3D array, the tradeoff is more complicated code, especially if malloc fails midway through the allocation loop (then you have to back out all the allocations you've made so far). It may also incur a performance penalty since the memory isn't guaranteed to be well-localized.
EDIT
As for saving this data in a file, it kind of depends on what you need to do.
The most portable is to save the data as formatted text, such as:
#include <stdio.h>
FILE *dat = fopen("myfile.dat", "w"); // opens new file for writing
if (dat)
{
for (i = 0; i < D0; i++)
{
for (j = 0; j < D1; j++)
{
for (k = 0; k < D2; k++)
{
fprintf(dat, "%f ", data[i][j][k]);
}
fprintf(dat, "\n");
}
fprintf(dat, "\n");
}
}
This writes the data out as a sequence of floating-point numbers, with a newline at the end of each row, and two newlines at the end of each "page". Reading the data back in is essentially the reverse:
FILE *dat = fopen("myfile.dat", "r"); // opens file for reading
if (dat)
{
for (i = 0; i < D0; i++)
for (j = 0; j < D1; j++)
for (k = 0; k < D2; k++)
fscanf(dat, "%f", &data[i][j][k]);
}
Note that both of these snippets assume that the array has a known, fixed size that does not change from run to run. If that is not the case, you will obviously have to store additional data in the file to determine how big the array needs to be. There's also nothing resembling error handling.
I'm leaving a lot of stuff out, since I'm not sure what your goal is.
Well, you can of course store it as a 3D array in C, too. Not sure why you feel you must convert to 2D:
double data[100][100][100];
This will of course require quite a bit of memory (around 7.6 MB assuming a 64-bit double), but that should be fine on a PC, for instance.
You might want to avoid putting such a variable on the stack, though.
c can handle 3-dimensional arrays, so why don't use that?
Writing it on a .mat file is a little bit of work, but it doesn't seem too difficult.
The .mat format is described here.
C handles multidimensional arrays (double array[K][M][N];) just fine, and they are stored contiguously in memory the same as a 1-D array. In fact, it's legal to write double* onedim = &array[0][0][0]; and then use the same exact memory area as both a 3-D and 1-D array.
To get it from C into matlab, you can just use fwrite(array, sizeof array[0][0][0], K*M*N*, fptr) in C and array = fread(fileID, inf, 'real*8') in MatLab. You may find that the reshape function is helpful.
Triple pointer:
double*** X;
X= (double***)malloc(k*sizeof(double**));
for(int i=0; i<k;i++)
{
X[i]=(double**)malloc(n*sizeof(double*));
for(int j=0; j<n;j++)
{
X[i][j]=(double*)malloc(m*sizeof(double));
}
}
This way the method to access at each value if quite intuitive: X[i][j][k].
If instead you want, you can use an unique array:
double* X;
X=(double*)malloc(n*m*k*sizeof(double));
And you access to each element this way:
X[i*n*m+j*n+k]=0.0;
If you use a triple pointer, don't forget to free the memory.

Why is this C program crashing?

I have a simple test program in C to scramble an array of values on the heap. Sidenote: I know the random logic here has a flaw that will not allow the "displaced" value to exceed RAND_MAX, but that is not the point of this post.
The point is that when I run the code with N = 10000, every once in a while it will crash with very little information (screenshots posted below). I'm using MinGW compiler. I can't seem to reproduce the crash for lower or higher N values (1000 or 100000 for example).
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int N = 10000;
int main() {
int i, rand1, rand2, temp, *values;
/* allocate values on heap and initialize */
values = malloc(N * sizeof(int));
for (i = 0; i < N; i++) {
values[i] = i + 1;
}
/* scramble */
srand(time(NULL));
for (i = 0; i < N/10; i++) {
rand1 = (int)(N*((double)rand()/(double)RAND_MAX));
rand2 = (int)(N*((double)rand()/(double)RAND_MAX));
temp = values[rand1];
values[rand1] = values[rand2];
values[rand2] = temp;
}
int displaced = 0;
for (i = 0; i < N; i++) {
if (values[i] != (i+1)) {
displaced++;
}
}
printf("%d numbers out of order\n", displaced);
free(values);
return 0;
}
it may be because rand() generates a random number from 0 to RAND_MAX inclusive so (int)(N*((double)rand()/(double)RAND_MAX)) can be N, which exceeds the array boundary. however, i don't see why that would vary with array size (it does explain why it only crashes sometimes, though).
try /(1+(double)RAND_MAX) (note that addition is to the double, to avoid overflow, depending on the value of RAND_MAX) (although i'm not convinced that will always work, depending on the types involved. it would be safer to test for N and try again).
also, learn to use a tool from Is there a good Valgrind substitute for Windows? - they make this kind of thing easy to fix (they tell you exactly what went wrong when you run your program).

Resources