cuda c并行做哈弗曼编码

统计可见字符频率

找一篇英文文章in.txt,统计各种可见字符的出现频率,并保存到文件out.txt:

#include<iostream>
using namespace std;
int main()
{
    int a[256]={0};
    //for()
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    char c;
    while(scanf("%c",&c)!=EOF)
    {
        a[(int)c]++;                         
    }   
    for(int i=0;i<128;i++)
    {
        c=char(i);       
        //cout<<i<<" "<<c<<" ";
        cout<<a[i]<<endl;
    }
}
哈弗曼编码

1 根据字符频率生成哈弗曼树

2 遍历哈弗曼树生成哈弗曼编码

3 从文件读入待编码序列

4 gpu分段生成待编码序列的哈弗曼编码

5 哈弗曼编码段组合并输出到文件

#include<iostream>
#include<fstream>
#include<queue>
using namespace std;
#define N 128  //max number of kinds of charecters to covert_encode
#define M 4    //number of charecters to encode in a thread
#define MM 20000 //max length of text to encode
#define HANDLE_ERROR(x) {if(x!=0) printf("error is caught on gpu: %d\n",x);}
struct node
{
    int v;
    char c;
    node *lchild;
    node *rchild; 
};
struct cmp
{
       bool operator()(const node &p1,const node &p2)
       {return p1.v>p2.v;} 
};

//根据哈弗曼编码规则dic,对待编码窜str进行编码,并将结果保存到part中
__global__ void cuda_fun_encode(char *dic,int *dicl,char *str,int *textlen,char *part,int *partl,int *threadNum)
{
    int tid=threadIdx.x;
    if(tid<(*threadNum))
    {
        partl[tid]=0;
        for(int i=tid*M;i<(tid+1)*M&&i<(*textlen);i++)
        {
            for(int j=0;j<dicl[str[i]];j++)
     {
                part[M*N*tid+(partl[tid]++)]=dic[(str[i])*N+j];
            } 
        }
       
    }
}

//生成哈弗曼树并得到哈弗曼编码
void search(node *root,string code,string *dic,int *dicl)
{  
    if(root->lchild!=NULL)
        search(root->lchild,code+"0",dic,dicl);
    if(root->rchild!=NULL)
        search(root->rchild,code+"1",dic,dicl);
    if(root->c==30)
        return;
    else
    {
        char c=root->c;
        cout<<c<<" "<<code<<endl;
        dic[c]=code;
        dicl[c]=code.length();
    }
}

int main()
{
    //begin*** get a encode scheme and store it in dic,dev_dic
    freopen("fre.txt","r",stdin);
    int freq[N];
    for(int i=0;i<N;i++)
        cin>>freq[i];
  
    priority_queue <node,vector<node>,cmp> q;
    for(int i=0;i<N;i++)
    {
        if(freq[i]==0)   
            continue;
 node oo;
        oo.v=freq[i];
        oo.c=char(i);
        oo.lchild=NULL;
        oo.rchild=NULL;
        q.push(oo);             
    }
    while(q.size()>1)
    {
        node *o,*l,*r;
        o=new node;
        l=new node;
        r=new node;
        *l=q.top();
        q.pop();
        *r=q.top();
        q.pop();
        o->lchild=l;
        o->rchild=r;
        o->v=l->v+r->v;
        o->c=30;//30 is an invisible character
        q.push(*o);
    }
   
    string dic[N];
    char dic2[N][N];
    int dicl[N];

//初始化
for(int i=0;i<N;i++)
{
dic[i] = "";
dicl[i] = 0;
for(int j=0;j<N;j++)
{
dic2[i][j] = 0;
}
}
    char *dev_dic;
    int *dev_dicl;
    HANDLE_ERROR(cudaMalloc((void**)&dev_dic, sizeof(char)*N*N));
    HANDLE_ERROR(cudaMalloc((void**)&dev_dicl,sizeof(int)*N));
    string code="";
    node head=q.top();
    search(&head,code,dic,dicl);
       
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<dic[i].length();j++)
        {
     dic2[i][j]=dic[i][j];
 }
    }
    printf("1111*********************\n");
    HANDLE_ERROR( cudaMemcpy(dev_dic,dic2, sizeof(char)*N*N,cudaMemcpyHostToDevice) );
    HANDLE_ERROR( cudaMemcpy(dev_dicl,dicl,sizeof(int)*N,cudaMemcpyHostToDevice) );
    printf("2222*********************\n");
    //end***get a encode scheme and store it in dic,dev_dic
    //begin*** read textfile into string (dev_)str,length is (dev_)textlen.
    char str[MM];
    char *dev_str;// store a copy of str in device
    int i=0;
    int textlen;//length of the text
    int *dev_textlen;//length of the text on gpu
    freopen("text.txt","r",stdin);
    while(scanf("%c",&str[i])!=EOF)
        printf("%c",str[i++]);
    textlen=i-1;
    printf("3333*********************\n");
    HANDLE_ERROR(cudaMalloc((void**)&dev_str,sizeof(char)*MM));
    HANDLE_ERROR(cudaMalloc((void**)&dev_textlen,sizeof(int)));
    HANDLE_ERROR(cudaMemcpy(dev_str,str,sizeof(char)*MM,cudaMemcpyHostToDevice));   
    HANDLE_ERROR(cudaMemcpy(dev_textlen,&textlen,sizeof(int),cudaMemcpyHostToDevice));   
    printf("4444*********************\n");
    //end*** read textfile into string (dev_)str,length is (dev_)textlen.
   
    //begin*** divide and encode
    int threadNum=1+(textlen-1)/M;
    int *dev_threadNum;
    char part[N*M*threadNum];//[N*M*MM];
    char *dev_part;
    int partl[threadNum];
    int *dev_partl;
  
    printf("5555*********************\n");
    HANDLE_ERROR(cudaMalloc((void**)&dev_threadNum,sizeof(int)));
    HANDLE_ERROR(cudaMemcpy(dev_threadNum,&threadNum,sizeof(int),cudaMemcpyHostToDevice) );
    HANDLE_ERROR(cudaMalloc((void**)&dev_part,sizeof(char)*N*M*threadNum));
    HANDLE_ERROR(cudaMalloc((void**)&dev_partl,sizeof(int)*(threadNum)));
    printf("6666*********************\n");

    cuda_fun_encode<<<1,threadNum>>>(dev_dic,dev_dicl,dev_str,dev_textlen,dev_part,dev_partl,dev_threadNum);

    printf("7777*********************\n");
    HANDLE_ERROR( cudaMemcpy(partl,dev_partl,sizeof(int)*threadNum,cudaMemcpyDeviceToHost) );
    HANDLE_ERROR( cudaMemcpy(part,dev_part,sizeof(char)*N*M*threadNum,cudaMemcpyDeviceToHost) );
    printf("8888*********************\n");
    //end*** divide and encode

    //begin*** show
    printf("#############################################\n");
    printf("the length of text is %d\n",textlen);
    for(int i=0;i<threadNum;i++)
    {
        printf("the length of part[%d] is %d\n",i,partl[i]);
        for(int j=0;j<partl[i];j++)
            printf("%c",part[i*N*M+j]);
        printf("\n");
    }
    printf("#############################################\n");
    //show*** show
    freopen("encode.txt","w",stdout);
    for(int i=0;i<threadNum;i++)
        for(int j=0;j<partl[i];j++)
         printf("%c",part[i*N*M+j]);

    cudaFree(dev_dic);
    cudaFree(dev_dicl);
    cudaFree(dev_str);
    cudaFree(dev_textlen);
    cudaFree(dev_threadNum);
    cudaFree(dev_part);
    cudaFree(dev_partl);

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值