0

我编写了一个程序,它接收一个文本文件作为输入并返回另一个文本文件作为输出。文本文件是使用 3D 应用程序 (Blender) 中的脚本 (python) 创建的,它包含一个顶点列表,这些顶点是方形网格的一部分。该程序接收该数据,将其存储在一个结构中,并返回一个形成较小正方形的顶点列表。然后,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");
}

我非常感谢制作这个多线程的任何帮助。处理真正的大数据需要很长时间(今天我尝试了一个 50mb 的文本文件,20 分钟后它只运行了 30 次(在我需要的 26000 上) ),而且由于所有使用它的电脑都至少有 4 个内核,我真的很想让它多线程!谢谢指教!:)

Ps:如果你需要,我也可以发布python脚本代码,但是它充满了对程序内部api的调用,所以我真的不知道它是否有用。

4

2 回答 2

0

当我分析您的代码在 200 万个随机顶点的示例数据集上运行时,将源文件预加载到页面缓存中,瓶颈是字符串到浮点数的转换(不过,它仍然只在 5 秒内运行 - 所以它不是那么慢)。

可以多线程将字符串转换为浮点数,并且通过仔细编码,您将通过这种方式获得一些收益。但是,如果改为更改 Python 代码以将浮点数写入可以由 C 代码直接加载的二进制格式(使用fread()),您将获得更多的收益。我相信你可以struct.pack在 Python 端使用来实现这一点。

代码的处理部分当然也可以改进,但在它成为瓶颈之前我不会担心它。

于 2011-01-27T04:01:57.993 回答
0

我不会专门通过您的代码工作,但您的算法可能能够应用 Map 和 Reduce。

这是一篇关于如何在 C 中使用它的文章:

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

于 2011-01-26T23:55:32.387 回答