我在从几个Threads收到的处理结果中遇到了一些问题。如果我正确使用openmp,我不确定。下面的代码摘录显示了我的代码的openmp部分。
参数:
线程私有:
it:映射迭代器(timestamp,userkey)
ite: map iterator((timestamp,userkey)/ int amount)
thread_result_map: typedef map< userkey(str),timestamp(str)>
何时,谁:匹配正则表达式(timestamp,userkey)
在线程之间共享:
日志:字符数组
尺寸: log.size()
标识符,时间戳,用户密钥: boost :: regex模式
combined_result_map: typedef map< thread_result_map,hits(int)>
#pragma omp parallel shared(log, size, identifier, timestamp, userkey) private(it, ite, str_time, str_key, vec_str_result, i, id, str_current, when, who, thread_result_map)
{
#pragma omp for
for (i = 0 ; i < size ; i++){
str_current.push_back(log[i]);
if (log[i] == '\n') {
if (boost::regex_search(str_current, identifier)){
boost::regex_search(str_current, when, timestamp);
str_time = when[0];
boost::regex_search(str_current, who, userkey);
str_key = who[0];
thread_result_map.insert(make_pair(str_time, str_key));
}
str_current = ""; //reset temp string
}
}
#pragma omp critical
{
for (it=thread_result_map.begin(); it!=thread_result_map.end(); it++) {
id = omp_get_thread_num();
cout << thread_result_map[it->first] <<
thread_result_map[it->second];
cout << "tID_" << id << " reducing" << endl;
}
}
}
正如您所看到的,每个线程都有自己的char数组分区,它从数组中逐行解析,如果当前字符串由“identifier”标识,则时间戳和用户密钥将添加到线程的私有结果映射中(串/串)。
现在循环之后我有几个线程的私有结果映射。 combined_result_map是地图内的地图。关键是线程结果的键/值的组合,值是该组合的出现量。
我只解析时间戳的一部分,所以当在1小时内,同一个用户密钥多次出现时,点击计数器将会增加。
结果应如下所示:
TIME(MMM/DD/HH/);USERKEY;HITS
May/25/13;SOMEKEY124345;3
因此,通过指定组合+ =结果,我在关键部分(我删除了)中的命中数量没有问题。
但是如何以相同的方式组合我的结果图?我知道我必须遍历线程映射,但是当我在循环中放置一个“cout”来测试每个线程只调用一次。
当我将所有正则表达式设置为“error”时,在我的本地syslog上运行测试会给出以下输出(以确保每个标识的行都有一个用户密钥和一个具有相同名称的时间戳):
解析访问字符串的模式:
error Pattern for parsing Timestamp:
error Pattern for parsing Userkey:
error
*** Parsing File /var/log/syslog
errortID_0 reducing errortID_1
reducing errortID_2 reducing
errortID_3 reducing
*** Ok! ________________ hits :
418 worktime: 0.0253871s
(计算的命中数来自线程专用计数器,我在上面的代码中删除了
所以我的4个线程中的每一个都会执行一个cout并离开循环,尽管所有这些都应该有418次点击。那我该怎么办?如何在openmp区域内迭代我的结果?
答案 0 :(得分:0)
我自己发现了这个问题,很抱歉提出了愚蠢的问题。
我试图多次添加相同的密钥,这就是为什么地图大小没有增加,每个线程只循环一次。
修改强>
如果有人对解决方案感兴趣如何组合线程结果,我就是这样做的。也许你看到任何可以改进的东西。
我刚刚将本地线程结果映射更改为pairs(str,str)
。
这是完整的openmp代码部分。 Pehaps它对任何人都有用:
#pragma omp parallel shared(log, size, identifier, timestamp, userkey) private(it, ite, str_time, str_key, i, id, str_current, when, who, local_res)
{
#pragma omp for
for (i = 0 ; i < size ; i++){
str_current.push_back(log[i]);
if (log[i] == '\n') { // if char is newline character
if (boost::regex_search(str_current, identifier)){ // if current line is access string
boost::regex_search(str_current, when, timestamp); // get timestamp from string
str_time = when[0];
boost::regex_search(str_current, who, userkey); // get userkey from string
str_key = who[0];
local_res.push_back((make_pair(str_time, str_key))); // append key-value-pair(timestamp/userkey)
id = omp_get_thread_num();
//cout << "tID_" << id << " - adding pair - my local result map size is now: " << local_res.size() << endl;
}
str_current = "";
}
}
#pragma omp critical
{
id = omp_get_thread_num();
hits += local_res.size();
cout << "tID_" << id << " had HITS: " << local_res.size() << endl;
for (i = 0; i < local_res.size(); i++) {
acc_key = local_res[i].second;
acc_time = local_res[i].first;
if(m_KeyDatesHits.count(acc_key) == 0) { // if there are no items for this key yet, make a new entry
m_KeyDatesHits.insert(make_pair(acc_key, str_int_MapType()));
}
if (m_KeyDatesHits[acc_key].count(acc_time) == 0) { // "acc_time" is a key value, if it doesn't exist yet, add it and set "1" as value
m_KeyDatesHits[acc_key].insert(make_pair(acc_time, 1 ));
it = m_KeyDatesHits.begin(); // iterator for userkeys/maps
ite = m_KeyDatesHits[acc_key].begin(); // iterator for times/clicks
} else m_KeyDatesHits[acc_key][acc_time]++; // if userkey already exist and timestamp already exists, count hits +1 for it
}
}
}
我做了一些测试,但它确实在快速运行。
使用4个线程,它会搜索150MB的LogFile以获取访问事件,从每个事件中解析自定义用户密钥和日期,并在4秒内组合结果。
在结束时,它会创建一个导出列表。这是程序输出:
HELLO,欢迎来到LogMap 0.1!
C ++ / OpenMP内存映射解析引擎
的 _ __ _ __ _ __ _ __ _ __ _ __ 可用的处理器数量= 4
线程数= 4用于解析访问字符串的模式:
用于的GET / _openbooknow / key / Pattern 解析时间戳:\ d {2} / \ w {3} / \ d {4}
用于解析Userkey的模式:
[a-zA-Z0-9] {20,32}* 解析文件
/home/c0d31n/Desktop/access_log-test.txtHITS:169147 HITS:169146 HITS:169146
HITS:169147* 好的! _ __ _ ____ 点击:
676586工作时间:4.03816s* 创建了新的导出文件:“。/ test.csv”
根@ c0d3b0x:〜/工作区/ OpenBookMap /释放#
cat test.csv
“1nDh0gV6eE3MzK0517aE6VIU0”; “28 / MAR / 2011”, “18813”
“215VIU1wBN2O2Fmd63MVmv6QTZy”; “28 / MAR / 2011”, “6272”
“36Pu0A2Wly3uYeIPZ4YPAuBy”; “18 /月/ 2011”, “18816”
“36Pu0A2Wly3uYeIPZ4YPAuBy”; “21 /月/ 2011”, “12544”
“36Pu0A2Wly3uYeIPZ4YPAuBy”; “22 / MAR / 2011”, “12544”
“36Pu0A2Wly3uYeIPZ4YPAuBy”; “23 /月/ 2011”, “18816”
“9E1608JFGk2GZQ4ppe1Grtv2”; “28 / MAR / 2011”, “12544”
“pachCsiog05bpK0kDA3K2lhEY”; “17 /月/ 2011”, “18029”
“pachCsiog05bpK0kDA3K2lhEY”; “18 /月/ 2011”, “12544”
“pachCsiog05bpK0kDA3K2lhEY”; “21 /月/ 2011”, “18816”
“pachCsiog05bpK0kDA3K2lhEY”; “22 / MAR / 2011”, “6272”
“pachCsiog05bpK0kDA3K2lhEY”; “23 /月/ 2011”, “18816”
“pachCsiog05bpK0kDA3K2lhEY”; “28 / MAR / 2011”, “501760”
“1nDh0gV6eE3MzK0517aE6VIU0”; “28 / MAR / 2011”, “18813”
“215VIU1wBN2O2Fmd63MVmv6QTZy”; “28 / MAR / 2011”, “6272”
“36Pu0A2Wly3uYeIPZ4YPAuBy”; “18 /月/ 2011”, “18816”
“36Pu0A2Wly3uYeIPZ4YPAuBy”; “21 /月/ 2011”, “12544”
“36Pu0A2Wly3uYeIPZ4YPAuBy”; “22 / MAR / 2011”, “12544”
“36Pu0A2Wly3uYeIPZ4YPAuBy”; “23 /月/ 2011”, “18816”
“9E1608JFGk2GZQ4ppe1Grtv2”; “28 / MAR / 2011”, “12544”
“pachCsiog05bpK0kDA3K2lhEY”; “17 /月/ 2011”, “18029”
“pachCsiog05bpK0kDA3K2lhEY”; “18 /月/ 2011”, “12544”
“pachCsiog05bpK0kDA3K2lhEY”; “21 /月/ 2011”, “18816”
“pachCsiog05bpK0kDA3K2lhEY”; “22 / MAR / 2011”, “6272”
“pachCsiog05bpK0kDA3K2lhEY”; “23 /月/ 2011”, “18816”
“pachCsiog05bpK0kDA3K2lhEY”;“28 / Mar / 2011”;“501760”