Многопоточность проходит через массив структур в C - PullRequest
0 голосов
/ 27 января 2011

Я написал программу, которая получает в качестве входных данных текстовый файл и возвращает в качестве выходных данных другой текстовый файл. Текстовый файл создается с помощью скрипта (python) внутри 3D-приложения (Blender) и содержит список вершин, которые являются частью квадратной сетки. Программа получает эти данные, сохраняет их в структуре и возвращает список вершин, которые образуют меньший квадрат. Затем 3D-приложение, снова со сценарием, считывает эти вершины и отделяет их от исходного меша. Делая это несколько раз, исходная сетка будет разделена на множество квадратов одной и той же области. СЕЙЧАС ОНА РАБОТАЕТ;) Но это ужасно мало. Когда вы делаете это на вершинах 200k, это занимает некоторое время, но для запуска на вершинах 1kk это требует времени

Здесь источник:

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct{
    int index;
    float x,y,z;
} vertex;
vertex *find_vertex(vertex *list, int len)
{
    int i;
    vertex lower,highter;
    lower=list[0];
    highter=list[1];
//find the lower lefter and the upper righter vertices
    for(i=0;i<len;i++)
    {
        if ((list[i].x<=lower.x) && (list[i].y<=lower.y))
            lower=list[i];
        if ((list[i].x>=highter.x) && (list[i].y>=highter.y))
            highter=list[i];
    }
    vertex *ret;//create a pointer for returning 2 structs
    ret=(vertex*)malloc(sizeof(vertex)*2);
    if (ret==NULL)
    {
        printf("Can't allocate the memory");
        return 0;
    }
    ret[0]=lower;
    ret[1]=highter;
    return ret;
}
vertex *square_list_of_vertex(vertex *list,int len,vertex start, float size)
{
    int i=0,a=0;
    unsigned int *num;
    num=(int*)malloc(sizeof(unsigned int)*len);
    if (num==NULL)
    {
        printf("Can't allocate the memory");
        return 0;
    }
    //controlls if point is in the right position and adds its index in the main list in another array
    for(i=0;i<len;i++)
    {
        if ((list[i].x-start.x)<size && (list[i].y-start.y<size))
        {
            if (list[i].y-start.y>-size/100)//it was adding also wrong vertices. This line is to solve a bug
            {
                num[a]=i;
                a++;//len of the return list
            }
        }
    }
    //create the list with the right vertices
    vertex *retlist;
    retlist=(vertex*)malloc(sizeof(vertex)*(a+1));
    if (retlist==NULL)
    {
        printf("Can't allocate the memory");
        return 0;
    }
    //the first index is used only as an info container
    vertex infos;
    infos.index=a+1;
    retlist[0]=infos;
    //set the value for the return pointer
    for(i=1;i<=a;i++)
    {
        retlist[i]=list[num[i-1]];
    }
    return retlist;
}
//the function that pass the data to python
void return_funct_1(vertex lower,vertex highter)
{
    FILE* ret;
    ret=fopen("max_min.txt","w");
    if (ret==NULL)
    {
        printf("Error opening the file\n");
        return;
    }
    fprintf(ret,"%i\n",lower.index);
    fprintf(ret,"%i\n",highter.index);
    fclose(ret);
}
//the function that pass the data to python
void return_funct_2(vertex *squarelist)
{
    FILE* ret;
    int i,len;
    ret=fopen("square_list.txt","w");
    if (ret==NULL)
    {
        printf("Error opening the file\n");
        return;
    }
    len=squarelist[0].index;
    for(i=1;i<len;i++)
    {
        //return all the informations
        //fprintf(ret,"%i %f %f %f\n",squarelist[i].index,squarelist[i].x,squarelist[i].y,squarelist[i].z);

        //just return the index(it's enought for the python script)
        fprintf(ret,"%i\n",squarelist[i].index);
    }
    fclose(ret);
}
//argv:
//function[1/2] number_of_vert(int) size_of_square(int) v_index(int) v_xcoord(float) v_ycoord(float) v_zcoord(float)...
//example of file: 2 4 2 0 1 2 3 1 1 2 3 2 1 2 3 3 1 2 3 4 1 2 3 //function 1, number of ver=4, size=2 and then the 4 vertex with their coords
int main(int argc, char *argv[])
{
    if(argc==1)
    {
        printf("%s need a path to a vectorlist file\n",argv[0]);
        return 0;
    }
    FILE* input;
    input=fopen(argv[1],"r");
    if (input==NULL)
    {
        printf("Error opening the file\n");
        return(0);
    }
    int func=0,i=0,a=0,u=0;
    char read;
    char* argument;
    argument=(char*)malloc(sizeof(char)*50);//yeah, i know, i should use list instead of an array, but when i first coded this i was quite in hurry (and i'm still  learning ) 
    //get the first paramater in the file
    argument[0]=fgetc(input);
    argument[1]='\0';
    func=atoi(argument);
    //skipp the space
    read=fgetc(input);
    //get the number of vertices;
    i=0;
    do {
        read=fgetc(input);
        argument[i]=read;
        i++;
    }while(read!=' ' && !feof(input) );
    //set the end of the string
    argument[i]='\0';
    //set the variable to the correct integer value;
    int vnumber=atoi(argument);
    i=0;
    do {
        read=fgetc(input);
        argument[i]=read;
        i++;
    } while(read!=' ' && !feof(input));
    //set the end of the string
    argument[i]='\0';
    float sqsize=atof(argument);
    vertex *list;
    //allocate memory in the array to fit the number of vertex needed
    list=(vertex*)malloc(sizeof(vertex)*vnumber);
    //control if the memory get allocated
    if (list==NULL)
    {
        printf("Can't allocate the memory");
        return 0;
    }
    //do the cycle for each vertex
    for(u=0;u<vnumber;u++)
    {
        //read the number and assign it to the proper value of the vertex
        for(a=0;a<4;a++)
        {
            i=0;
            do
            {
                read=fgetc(input);
                argument[i]=read;
                i++;
            } while(read!=' ' && !feof(input));
            argument[i]='\0';

            if(a==0)
                list[u].index=atoi(argument);
            if(a==1)
                list[u].x=atof(argument);
            if(a==2)
                list[u].y=atof(argument);
            if(a==3)
                list[u].z=atof(argument);
        }
    }
    //close the file
    fclose(input);
    if (func==1)
    {
        //find the lowest vertex and the higtest vertex
        vertex lower;
        vertex highter;
        vertex *lohi;
        lohi=(vertex*)find_vertex(list, vnumber);
        lower=lohi[0];
        highter=lohi[1];
        free(lohi);
        return_funct_1(lower,highter);//the function that return the data to python
        return 1;
    }
    if(func==2)
    {
        //find the list to return
        vertex *lohi;
        lohi=(vertex*)find_vertex(list, vnumber);
        vertex lower;
        lower=lohi[0];
        free(lohi);
        return_funct_2(square_list_of_vertex(list,vnumber, lower, sqsize));//the function that return the data to python
        return 1;
    }
    printf("Function argument was wrong: nothing was done\n");
}

Я был бы очень признателен за любую помощь в создании этого многопоточного приложения. Требуется время, чтобы работать с действительно большими данными (сегодня я пробовал использовать текстовый файл размером 50 МБ, а через 20 минут он работал только 30 раз (на 26000). мне нужно)), и так как почти все ПК, которые будут использовать это, будут иметь как минимум 4 ядра, я бы очень хотел получить его многопоточным! Спасибо за совет! :)

Ps: если вам нужно, я тоже могу опубликовать код скрипта Python, но он достаточно полон вызовов внутреннего API программы, поэтому я не знаю, будет ли он полезным.

Ответы [ 2 ]

0 голосов
/ 27 января 2011

Когда я профилирую ваш код, работающий над образцом набора данных из 2 миллионов случайных вершин, с исходным файлом, предварительно загруженным в кэш страницы, узким местом является преобразование строк в плавающие (хотя это все еще выполняется всего за 5 секунд - так что этоне , что медленно).

Возможно многопоточное преобразование строк в числа с плавающей точкой, и при тщательном кодировании вы получите некоторые выгоды таким образом.Тем не менее, вы получите гораздо больший выигрыш, если вместо этого вы измените код Python для записи чисел с плавающей запятой в двоичном формате, который может быть непосредственно загружен кодом C (с fread()).Я считаю, что вы можете использовать struct.pack на стороне Python для достижения этой цели.

Обрабатывающая часть вашего кода, безусловно, тоже может быть улучшена, но пока это не является узким местом, я бы не сталбеспокоиться об этом.

0 голосов
/ 27 января 2011

Я не собираюсь конкретно работать с вашим кодом, но ваш алгоритм может применить Map и Reduce.

Это статья о том, как вы можете использовать его в C:

http://pages.cs.wisc.edu/~gibson/mapReduceTutorial.html

...