OpenMP并行加速笛卡尔乘积

1.代码描述

以下代码在Linux平台编译运行,稍作修改可移植到Windows平台。其功能是通过多个字典字符集生成对应的笛卡尔乘积。并通过OpenMP并行加速。

正确性已在实际项目中通过验证。

2.源码

#include <pthread.h>
#include <omp.h>

#include <iostream>
#include <map>
#include <string>
using namespace std;

typedef unsigned char uint8;

//字典字符集与段字符集
struct charset_mem{
    int high,width;                     //字符集的宽度和高度
    int mem_size;                       //字符集data所占用的内存,单位字节
    uint8 *data;                        //字符集的数据
    char name[128];                     //字符集名称
};

map<string,charset_mem*> dic_utf8_charset_map; //全局字典字符集缓存
map<string,charset_mem*> dic_ucs2_charset_map; //全局字典字符集缓存
map<string,charset_mem*> seg_charset_map;      //全局段字符集缓存

pthread_mutex_t charset_mutex; 

//功能:根据多个字典字符集生成相应的笛卡尔乘积
//参数:charsetID:笛卡尔乘积结果字符集名称,dicNum:字典字符集数目,dicName:字典字符集名称数组指针,encode:字典字符编码类型
//返回值:成功返回true,失败返回false
bool cartesianProduct(string charsetID,  int dicNum, char(*dicName)[128],uint8 encode)
{
        pthread_mutex_lock(&charset_mutex);    //对字符集的map关联容器修改需要加锁
        string charsetNewedID=charsetID;
        map<string,charset_mem*>::iterator iter;

        charset_mem* segNewedCharset=new charset_mem;
        memset(segNewedCharset,0,sizeof(charset_mem));
        strcpy(segNewedCharset->name,charsetNewedID.c_str());

        #define MAX_WORD_LEN 40
        #define MAX_DIC_NUM 32

        //笛卡尔乘积(cartesian product)准备工作
        map<string,charset_mem*>&  dic_charset_map=(0==encode)?dic_utf8_charset_map:dic_ucs2_charset_map;
        int high=1,width=0;
        int s[MAX_DIC_NUM]={0};                         //字典段进制位
        for(int i=dicNum-1; i>=0; --i){
            cout<<"dicName["<<i<<"]:"<<dicName[i]<<endl;
            iter=dic_charset_map.find(dicName[i]);
            if(iter==dic_charset_map.end()){
                cout<<dicName[i]<<"do not exist"<<endl;
                pthread_mutex_unlock(&charset_mutex);
                return false;
            }
            s[i]=high;
            high*=iter->second->high;
            width+=iter->second->width;
        }

        segNewedCharset->high=high;
        segNewedCharset->width=width;
        segNewedCharset->data=new uint8[high*width];    

        //笛卡尔乘积
        int thread_num=omp_get_max_threads();//获取处理器最大可并行的线程数
        #pragma omp parallel for num_threads(thread_num) 
        for(int i=0;i<high;++i){
            uint8 wordTmp[MAX_WORD_LEN]={0};
            map<string,charset_mem*>::iterator iterTmp;
            int offset=0;
            int charpos=i;          
            for(int j=0;j<dicNum;++j){
                iterTmp=dic_charset_map.find(dicName[j]);   
                int indexDic=charpos/s[j];
                int offsetDic=indexDic*iterTmp->second->width;
                memcpy(wordTmp+offset,iterTmp->second->data+offsetDic,iterTmp->second->width);
                charpos=charpos%s[j];
                offset+=iterTmp->second->width;
            }
            memcpy(segNewedCharset->data+i*segNewedCharset->width,wordTmp,segNewedCharset->width);
        }

        //将结果字符集添加到,map映射表
        seg_charset_map.insert(pair<string,charset_mem*>(charsetNewedID,segNewedCharset));
        pthread_mutex_unlock(&charset_mutex);
        return true;
}

你可能感兴趣的:(OpenMP并行加速笛卡尔乘积)