2011-01-26 17 views
0

私は入力としてテキストファイルを受け取り、出力として別のテキストファイルを返すプログラムを作成しました。 テキストファイルは3Dアプリケーション(Blender)内にスクリプト(python)で作成され、正方形メッシュの一部である頂点のリストを含んでいます。プログラムはそのデータを受け取り、構造体に格納し、小さな正方形を形成する頂点のリストを返します。 3Dアプリケーションは、スクリプトを使用してこの頂点を読み取り、それらを元のメッシュから分離します。これを数回行うと、元のメッシュは同じエリアの多くの四角形に分割されます。 NOW BY 、ITワークス;) しかし、ひどく低い..です200kの頂点でそれをやったとき、それは時間がかかりますが、1kk頂点上でそれを実行すると、それはここでC言語で構造体の配列を処理するマルチスレッド

ソース年齢を取る:

#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私は必要)で作業するために年齢がかかります。 )、これを使用するかなりのPCは少なくとも4つのコアを持っているので、私はそれをマルチスレッドにしたいと思っています! アドバイスありがとうございます! :)

Ps:必要があれば、私もPythonのスクリプトコードを投稿することができますが、プログラムの内部APIへの呼び出しがかなりあるので、本当に有用かどうかはわかりません。

+0

ここで*具体的な質問は何ですか? –

+0

質問は次のとおりです。「これをマルチスレッド化するのを手伝ってもらえますか? –

+0

@Greg:しかし、非常に具体的な質問ではありません! –

答えて

0

私はあなたのコードで具体的に作業するつもりはありませんが、あなたのアルゴリズムはMap and Reduceを適用できるかもしれません。

これは、あなたがCでそれを使用する方法の記事です:

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

0

私はあなたのコードをページにプリロードソースファイルで、200万ランダム頂点のサンプルデータセット上で実行中のプロファイルときキャッシュは文字列を浮動小数点に変換するボトルネックです(ただし、まだ5秒で実行されます)。ではなく、が遅いです。

文字列から浮動小数点への変換をマルチスレッド化することができます。注意深くコーディングすれば、このようにいくつかの利点が得られます。しかし、Cコード(fread())で直接ロードできるバイナリ形式で浮動小数点数を書き込むようにPythonコードを変更すると、はるかにお金を稼ぐことができます。私はこれを達成するためにPython側でstruct.packを使用できると信じています。

コードの処理部分も確実に改善できますが、ボトルネックになるまでは心配しません。

+0

ありがとう、ありがとう!ここでは、binファイルをpythonで保存する方法を学びます。 Ps:コードのプロファイリングにどのようなプログラムを使用しましたか? –

+0

@Makers_F:[Perf](https://perf.wiki.kernel.org/index.php/Main_Page)を使用しました。 – caf