Parallel file reading OpenMP - c

I would like to develop a simple program that can read different pieces of a file simultaneously.
I'm using C, OpenM and GCC.
I have a file with the following structure:
--------
| HEADER |
| ARRAY1 |
| TEXT |
| ARRAY2 |
--------
Keeping in mind that the HEADER and ARRAY1 sections are independent of each other, I would like to understand if I can use a multi-thread strategy to read these first pieces of the file at the same time.
I implemented a very easy test solution.
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
typedef unsigned char BYTE;
typedef struct FILEHEADER {
int x;
int y;
int elemNr;
} FileHeader;
static const char *filename = "test_data.bin";
void readFileHeader(FILE *fp, FileHeader *header, int nr)
{
fread(header, sizeof(int), nr, fp);
}
void readArray1(FILE *fp, int *array1, int n)
{
fseek(fp, sizeof(FileHeader), SEEK_SET);
fread(array1, sizeof(int), sizeof(int) * n, fp);
}
int main(int argc, char *argv[]) {
int thread_count = strtol(argv[1], NULL, 10);
omp_set_num_threads(thread_count);
const int n = 10;
// create the file and write the data inside
FILE *fp = fopen(filename, "wb");
FileHeader headerW = {.x = 5, .y = 9, .elemNr = 3};
BYTE *buffer = (BYTE*)&headerW;
fwrite(buffer, sizeof(BYTE), sizeof(int) * headerW.elemNr, fp);
int *array = calloc (n, sizeof(int));
for (int i = 0; i < n; i++)
array[i] = i;
buffer = (BYTE*)array;
fwrite(buffer, sizeof(BYTE), sizeof(int) * n, fp);
printf("write section\n");
printf("\nheader:\n\t");
printf("x: %d\n\ty: %d\n\telemNr: %d\n", headerW.x, headerW.y, headerW.elemNr);
printf("\narray:\n");
for (int i = 0; i < n; i++)
printf("\tarray[%d]: %d\n", i, array[i]);
printf("\n");
free(array);
fclose(fp);
// open the file and read the data inside
FILE *fp1 = fopen(filename, "rb");
FILE *fp2 = fopen(filename, "rb");
FileHeader headerR = {.x = 0, .y = 0, .elemNr = 0};
int *array1 = calloc (n, sizeof(int));
#pragma omp parallel sections
{
#pragma omp section
readFileHeader(fp1, &headerR, 3);
#pragma omp section
readArray1(fp2, array1, n);
}
printf("read section\n");
printf("\nheader:\n\t");
printf("x: %d\n\ty: %d\n\telemNr: %d\n", headerR.x, headerR.y, headerR.elemNr);
printf("\narray1:\n");
for (int i = 0; i < n; i++)
printf("\tarray1[%d]: %d\n", i, array1[i]);
// read the other parts of the file and do something
free(array1);
fclose(fp2);
fclose(fp1);
return 0;
}
This solution compiles and works.
However because of its simplicity, I'm not sure if it is really run in parallel.
Anyway, what I'm asking is if the idea behind is correct, in other words, can I safely read different parts of the same file, at the same time, by using a multi-thread strategy?
If the answer were to be no, there is another way to do that by using OpenMp?

Related

Problem while reading structure from binary file

As I was trying to write code which is supposed to sort some structures in a file by a specific field (key), I noticed that my function won't read the key correctly. I don't have any idea what I am doing wrong. The code is not complete.
The constr function is supposed to read one structure at a time from the binary file, then only save the varsta array. However, if I try to see what value I obtained, the values are not the ones I gave.
This is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char nume[20];
char prenume[20];
float varsta;
} PERS;
typedef struct
{
float key;
int nr;
}INDEX;
int constr(FILE *f, INDEX tabl[])
{
int n;
n = ftell(f) / sizeof(PERS);
int i, depl = 0;
PERS p;
for (i = 0; i < n; i++)
{
fseek(f, depl, 0);
fread(&p, sizeof(p), 1, f);
tabl[i].key = p.varsta;
tabl[i].nr = i;
depl += sizeof(PERS);
}
return n;
}
int main()
{
FILE *f;
PERS pers[3];
if ((f = fopen("fis.txt", "wb+")) == NULL)
{
printf("Not ok");
exit(1);
}
int i;
for (i = 0; i < 3; i++)
{
scanf("%s%s%f", &pers[i].nume, &pers[i].prenume, &pers[i].varsta);
fwrite(&pers[i], sizeof(PERS), 1, f);
}
INDEX tabl[3];
int n = constr(f, tabl);
printf("%d", tabl[2].key); //only to check if the key is correct
fclose(f);
}
The key field is a float, but you are trying to print an integer.
Change the penultimate line in your code to
printf("%.2f\n", tabl[2].key);

Read/Write to file using void pointers in C

As part of a college assignment, I'm trying to do a simple C app, using Win32 for GUI programming and writing my own dynamic linked list for storing data. Since i could use it for other things later, I'm trying to write a generic list, with "built in" functions for reading and writing data to a file. Now here's my problem
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tagA{
int t_int;
float t_float;
char t_char;
char t_vchar[30];
} A;
typedef struct tagB{
void *data;
struct tagB *prox;
} B;
int main(){
A dA = {1, 1.5, 'a', "teste123"};
B dB = {&dA, NULL};
dB.data = &dA;
B dB2 = {0};
FILE *fp;
fp = fopen("Data.txt", "w");
size_t dSize = sizeof(dA);
printf("Struct size: %d", dSize);
if(fp == NULL){
printf("nope");
}else{
fwrite(&dB.data, dSize, 1, fp);
}
fclose(fp);
fp = fopen("Data.txt", "r");
dB2.data = malloc(dSize);
fread(&dB2.data, dSize, 1, fp);
printf("\n\n%s", ((A*)dB2.data)->t_vchar);
}
This is the code I'm trying to work out.
The writing works just fine, and I just have to make it to a separate function that receives the pointer to the data struct and its size.
But the reading is off... Once read and printed to the console, the t_int shows a really large number, the t_float has nothing, and so the char and string...
Also, I know its not the best written, most efficient and safe code, but it's just a prototype, something that came into my mind...
Your problem is you are writing the address of &dB.data with fwrite instead of dB.data itself (it is already a pointer). For example:
fwrite(dB.data, dSize, 1, fp);
will resolve your problem (with the like corresponding change to fread).
void *data;
It's not useful to declare data as void*. Declare it as A *data; instead.
fwrite(&dB.data, dSize, 1, fp);
...
fread(&dB2.data, dSize, 1, fp);
dB2.data is a pointer, just use dB2.data. See example below. For better readability you can declare ptr_data instead of data
typedef struct tagA {
int t_int;
float t_float;
char t_char;
char t_vchar[30];
} A;
typedef struct tagB {
A *data;
struct tagB *prox;
} B;
int main() {
A dA = { 1, 1.5, 'a', "teste123" };
B dB = { 0 };
dB.data = &dA;
B dB2 = { 0 };
FILE *fp;
fp = fopen("Data.txt", "w");
size_t dSize = sizeof(dA);
printf("Struct size: %d", dSize);
if(fp == NULL) {
printf("nope");
}
else {
fwrite(dB.data, dSize, 1, fp);
}
fclose(fp);
fp = fopen("Data.txt", "r");
dB2.data = malloc(dSize);
fread(dB2.data, dSize, 1, fp);
printf("\n\n%s\n", dB2.data->t_vchar);
return 0;
}
Your error is at fwrite(), fread(). The first param of them is the pointer which points at the real data you want to write/read.
Since you want to read/write a struct A, the pointer must actually point at struct A, not struct A*.
Just replace
fwrite(&dB.data, dSize, 1, fp);
fread(&dB2.data, dSize, 1, fp);
with
fwrite(dB.data, dSize, 1, fp);
fread(dB2.data, dSize, 1, fp);

Write and read struct with dynamic arrays and gsl_vectors in C

I have an structure similar to:
typedef struct FOO {
int m,n;
int * am;
gsl_vector * bn;
} foo;
To allocate this structures I do:
foo * bar;
bar=foo_alloc ( 10, 10 );
Where
foo * foo_alloc ( int m, int n ) {
foo * f = (foo*)malloc(sizeof(foo));
f->m=m;
f->n=n;
f->am=(int*)calloc(m,sizeof(int));
f->bn=gsl_vector_calloc(n);
return f;
}
I wish to write bar in a binary file and then read it again... How can I do this?
Thanks!
EDIT:
To be more specific, I tried with
fwrite(&bar,sizeof(*bar),1,file)
but sizeof(*bar) didn't work and by Google search I found that sizeof don't work with this kind of structures with dynamic arrays inside.
Is there a way to obtain the size of bar?
If not, I supouse I have to place an fwrite for each element, but in this case I don't know how to obtain the size of gsl_vector since this is also another structure with a dynamic array inside.
sizeof(*bar) is correct. It's &bar that's wrong. Since bar is a pointer, you shouldn't use the address-of operator.
Also, you've only attempted to write the struct and haven't written the dynamically-allocated array data. Actually, writing the struct is pointless since the addresses will not be valid when the data is read back. You should just write the sizes (m and n) and the array data. When you read it back you need to malloc/calloc the struct and array space again.
Here's a runnable example. I've replaced your gsl_vectors with double to make it easier for other people to run.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int m, n;
int *am;
double *bn;
} Foo;
void foo_write(Foo *f, FILE *file) {
fwrite(&(f->m), sizeof(f->m), 1, file);
fwrite(&(f->n), sizeof(f->n), 1, file);
fwrite(f->am, sizeof(*(f->am)), f->m, file);
fwrite(f->bn, sizeof(*(f->bn)), f->n, file);
}
Foo *foo_read(FILE *file) {
Foo *f = malloc(sizeof(*f));
fread(&(f->m), sizeof(f->m), 1, file);
fread(&(f->n), sizeof(f->n), 1, file);
f->am = malloc(f->m * sizeof(*(f->am)));
f->bn = malloc(f->n * sizeof(*(f->bn)));
fread(f->am, sizeof(*(f->am)), f->m, file);
fread(f->bn, sizeof(*(f->bn)), f->n, file);
return f;
}
Foo *foo_alloc(int m, int n) {
Foo *f = malloc(sizeof(*f));
f->m = m;
f->n = n;
f->am = calloc(f->m, sizeof(*(f->am)));
f->bn = calloc(f->n, sizeof(*(f->bn)));
return f;
}
void foo_print(Foo *f) {
int i;
printf("%d, %d\n", f->m, f->n);
for (i = 0; i < f->m; ++i)
printf("%d ", f->am[i]);
putchar('\n');
for (i = 0; i < f->n; ++i)
printf("%.1f ", f->bn[i]);
}
void foo_free(Foo *f) {
free(f->am);
free(f->bn);
free(f);
}
int main() {
FILE *file;
Foo *bar;
int i;
bar = foo_alloc(5, 10);
for (i = 0; i < bar->m; ++i)
bar->am[i] = i;
for (i = 0; i < bar->n; ++i)
bar->bn[i] = i;
file = fopen("foo.bin", "wb");
foo_write(bar, file);
fclose(file);
foo_free(bar);
file = fopen("foo.bin", "rb");
bar = foo_read(file);
fclose(file);
foo_print(bar);
return 0;
}
You may be able to write and read the gsl_vectors like this (assuming the vectors are independent, i.e., that they don't share data blocks):
void foo_write(Foo *f, FILE *file) {
size_t i;
fwrite(&(f->m), sizeof(f->m), 1, file);
fwrite(&(f->n), sizeof(f->n), 1, file);
fwrite(f->am, sizeof(*(f->am)), f->m, file);
for (i = 0; i < f->n; ++i)
gsl_vector_fwrite(file, &(f->bn[i]));
}
Foo *foo_read(FILE *file) {
size_t i;
Foo *f = malloc(sizeof(*f));
fread(&(f->m), sizeof(f->m), 1, file);
fread(&(f->n), sizeof(f->n), 1, file);
f->am = malloc(f->m * sizeof(*(f->am)));
f->bn = malloc(f->n * sizeof(*(f->bn)));
fread(f->am, sizeof(*(f->am)), f->m, file);
for (i = 0; i < f->n; ++i)
gsl_vector_fread(file, &(f->bn[i]));
return f;
}

getting fscanf to store in structs in C

I have an assignment where I need to get Values of RLC circuits from a file and calculate the resonant frequency however my issue is when I use the fscanf function it reads only the first line of the file and the rest comes out as zeros .
#include <stdio.h>
data
int h;
typedef struct cct
{
int code[50];
float R[50];
float L[50];
float C[50];
} CCT;
int read(CCT cct[], int n_p, FILE* fp){
char temp;
if(fp==NULL){
printf("Error\n");
return -1;
}
fscanf(fp,"%d,%f,%e,%e\n", cct[n_p].code, cct[n_p].R,cct[n_p].L, &cct[n_p].C);
}
int main()
{
FILE* fp = fopen("U://datafile.txt", "rt");
int i = 0;
CCT cct[50];
int size;
while (!feof(fp)) {
read(cct, i, fp);
i++;
}
size = i;
for (i = 0; i < size; ++i)
printf("%d,%0.2f,%0.2f,%0.2f\n", cct[i].code[i], cct[i].R[i],
cct[i].L[i], cct[i].C[i]);
scanf("%d",&h);
fclose(fp);
}
and this is the data file
1,4.36,2.23e-2,4.65e-8
2,4.57,2.01e-2,5.00e-8
3,3.99,2.46e-2,4.82e-8
4,4.09,2.60e-2,4.70e-8
I would appreciate if someone could point put why it only gets the first line. Thanks
CCT is composed of multiple arrays (you have arrays of arrays, which is wrong for the exercise, but that's not the point) and you always write to the element zero of the arrays. For example, cct[n_p].code in fscanf() is the address of the array, which is identical to the address of cct[n_p].code[0]. Then you print code[i] in the output loop, which is blank except for i == 0.
fscanf(fp,"%d,%f,%e,%e", cct[n_p].code, cct[n_p].R,cct[n_p].L, cct[n_p].C);
...
printf("%d,%0.2f,%0.2f,%0.2f\n", cct[i].code[0], cct[i].R[0], cct[i].L[0], cct[i].C[0]);
Something like the following, perhaps
#include <stdio.h>
typedef struct cct {
int code;
float R;
float L;
float C;
} CCT;
int h;
int read(CCT cct[], int n_p, FILE* fp){
char temp;
if(fp==NULL){
printf("Error\n");
return -1;
}
fscanf(fp,"%d,%f,%e,%e\n", &cct[n_p].code, &cct[n_p].R, &cct[n_p].L, &cct[n_p].C);
}
int main(){
FILE* fp = fopen("U://datafile.txt", "rt");
int i = 0;
CCT cct[50];
int size;
while (!feof(fp)) {
read(cct, i, fp);
i++;
}
size = i;
for (i = 0; i < size; ++i)
printf("%d,%0.2f,%0.2f,%0.2f\n", cct[i].code, cct[i].R, cct[i].L, cct[i].C);
scanf("%d",&h);
fclose(fp);
}

Struct arrays in C

Hi I'm having trouble trying to initializing each element of the struct array. When I try and assign the value ZERO to both 'bSize' and 'msgs', it doesn't work as it errors out when i get to malloc. In the printf statement it prints a -1852803823 number. Excuse the messy code as i'm playing around trying to figure it out.
struct message{
int *data;
int bSize;
int msgs;
};
int main(int argc, char *argv[]) {
.....
}
void getSchedFile (FILE *file, int **schd) {
struct message sMsg[nodeCount];
const int pakSize = 6;
// Iniitialise message buffer
for (int i=0; i<nodeCount; i++){
sMsg[i].bSize = 0;
sMsg[i].msgs = 0;
printf("bSize %d\n",sMsg[i].bSize);
}
/* Get the number of bytes */
fseek(file, 0L, SEEK_SET);
int time;
while((fscanf(file, "%d", &time)) != EOF){
int src;
fscanf(file, "%d", &src); // get source node id
// These are here for easier reading code
int aPos = sMsg[src].bSize;
int nMsg = sMsg[src].msgs;
printf("size %d\n", sMsg[src].bSize);
if (sMsg[src].bSize==0){
sMsg[src].data = malloc( pakSize * sizeof(int));
}else{
sMsg[src].data = realloc(sMsg[src].data, (aPos+pakSize)*sizeof(int));
}
Where is the nodeCount value coming from? Is it a global variable? You should be very careful with global variables, and avoid using them if possible.
Pass the nodeCount in the method parameter and as Charlie mentioned, check it for > 0

Resources