开发者

Combine Thread Results with openmp

开发者 https://www.devze.com 2023-03-06 18:14 出处:网络
I have some problems combining the processing results I recieve from several Threads. And I\'m not sure, if I use openmp correctly. The below code extract shows the openmp portion of my code.

I have some problems combining the processing results I recieve from several Threads. And I'm not sure, if I use openmp correctly. The below code extract shows the openmp portion of my code.

Parameters:

thread private:

it: map iterator (timestamp, userkey)

ite: map iterator ((timestamp,userkey)/int amount)

thread_result_map: typedef map < userkey(str),timestamp(str) >

when, who: matching regex (timestamp, userkey)

shared among threads:

log: char array

size: log.size()

identifier, timestamp, userkey: boost::regex patterns

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++){
       开发者_如何学C     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;
            }
        }
    }

As you can see every thread has his own partition of the char array, it parses line by line from the array and if the current string is identified by "identifier", the timestamp and userkey are added to the thread's private result map (string/string).

Now after the loop I have several thread's private result maps. The combined_result_map is a map inside a map. The key is the combination of key/value of the threads result and the value is the amount of occurences of this combination.

I'm parsing only a portion of the timestamp so when in 1 hour the same userkey appears multiple times the hit counter will be increased.

The result should look something like this:

TIME(MMM/DD/HH/);USERKEY;HITS
May/25/13;SOMEKEY124345;3

So I have no problems combining hit amounts in the critical section (which I removed) by specifying combined+=results.

But how can I combine my result maps the same way? I know I have to iterate through threads maps, but when I put a "cout" inside the loop for testing every thread calls it only once.

A test run on my local syslog gives me the following output when I set all the regex to "error" (to make sure every identified line will have a userkey and a timestamp with the same name):

Pattern for parsing Access String:

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

(The calculated hits come from thread private counters, that I removed in the code above)

So every of my 4 threads does a single cout and leaves the loop, although all together should have 418 hits. So what do I do wrong? How do I iterate through my results from inside my openmp area?


Found the problem myself, sorry for asking stupid questions.

I was trying to add the same key multiple times, that's why map size didn't increase and every thread looped only once.

Edit:

If anybody is interested in the solution how to combine thread results, this is how I did it. perhaps you see anything that could be improved.

I just changed the local threads result map to a vector of pairs(str,str).

This is the full working openmp code section. Pehaps it's useful for anyone:

#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

            }
        }
    }

I did some tests and it's really running fast.

Using 4 Threads this searches a 150MB LogFile for access events, parses a custom user key and date from every event and combines the results in under 4 seconds.

At the End it creates a export list. This is the program output:

HELLO, welcome to LogMap 0.1!

C++/OpenMP Memory Map Parsing Engine
__________________ Number of processors available = 4
Number of threads = 4

Pattern for parsing Access String:
GET /_openbooknow/key/ Pattern for
parsing Timestamp: \d{2}/\w{3}/\d{4}
Pattern for parsing Userkey:
[a-zA-Z0-9]{20,32}

* Parsing File
/home/c0d31n/Desktop/access_log-test.txt

HITS: 169147 HITS: 169146 HITS: 169146
HITS: 169147

* Ok! ________ hits :
676586 worktime: 4.03816s

* new export file created: "./test.csv"

root@c0d3b0x:~/workspace/OpenBookMap/Release#
cat test.csv
"1nDh0gV6eE3MzK0517aE6VIU0";"28/Mar/2011";"18813"
"215VIU1wBN2O2Fmd63MVmv6QTZy";"28/Mar/2011";"6272"
"36Pu0A2Wly3uYeIPZ4YPAuBy";"18/Mar/2011";"18816"
"36Pu0A2Wly3uYeIPZ4YPAuBy";"21/Mar/2011";"12544"
"36Pu0A2Wly3uYeIPZ4YPAuBy";"22/Mar/2011";"12544"
"36Pu0A2Wly3uYeIPZ4YPAuBy";"23/Mar/2011";"18816"
"9E1608JFGk2GZQ4ppe1Grtv2";"28/Mar/2011";"12544"
"pachCsiog05bpK0kDA3K2lhEY";"17/Mar/2011";"18029"
"pachCsiog05bpK0kDA3K2lhEY";"18/Mar/2011";"12544"
"pachCsiog05bpK0kDA3K2lhEY";"21/Mar/2011";"18816"
"pachCsiog05bpK0kDA3K2lhEY";"22/Mar/2011";"6272"
"pachCsiog05bpK0kDA3K2lhEY";"23/Mar/2011";"18816"
"pachCsiog05bpK0kDA3K2lhEY";"28/Mar/2011";"501760"
"1nDh0gV6eE3MzK0517aE6VIU0";"28/Mar/2011";"18813"
"215VIU1wBN2O2Fmd63MVmv6QTZy";"28/Mar/2011";"6272"
"36Pu0A2Wly3uYeIPZ4YPAuBy";"18/Mar/2011";"18816"
"36Pu0A2Wly3uYeIPZ4YPAuBy";"21/Mar/2011";"12544"
"36Pu0A2Wly3uYeIPZ4YPAuBy";"22/Mar/2011";"12544"
"36Pu0A2Wly3uYeIPZ4YPAuBy";"23/Mar/2011";"18816"
"9E1608JFGk2GZQ4ppe1Grtv2";"28/Mar/2011";"12544"
"pachCsiog05bpK0kDA3K2lhEY";"17/Mar/2011";"18029"
"pachCsiog05bpK0kDA3K2lhEY";"18/Mar/2011";"12544"
"pachCsiog05bpK0kDA3K2lhEY";"21/Mar/2011";"18816"
"pachCsiog05bpK0kDA3K2lhEY";"22/Mar/2011";"6272"
"pachCsiog05bpK0kDA3K2lhEY";"23/Mar/2011";"18816"
"pachCsiog05bpK0kDA3K2lhEY";"28/Mar/2011";"501760"

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号