1d86ed7fbStbbdev /*
2*b15aabb3Stbbdev Copyright (c) 2005-2021 Intel Corporation
3d86ed7fbStbbdev
4d86ed7fbStbbdev Licensed under the Apache License, Version 2.0 (the "License");
5d86ed7fbStbbdev you may not use this file except in compliance with the License.
6d86ed7fbStbbdev You may obtain a copy of the License at
7d86ed7fbStbbdev
8d86ed7fbStbbdev http://www.apache.org/licenses/LICENSE-2.0
9d86ed7fbStbbdev
10d86ed7fbStbbdev Unless required by applicable law or agreed to in writing, software
11d86ed7fbStbbdev distributed under the License is distributed on an "AS IS" BASIS,
12d86ed7fbStbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d86ed7fbStbbdev See the License for the specific language governing permissions and
14d86ed7fbStbbdev limitations under the License.
15d86ed7fbStbbdev */
16d86ed7fbStbbdev
17d86ed7fbStbbdev #include <iostream>
18d86ed7fbStbbdev #include <string>
19d86ed7fbStbbdev #include <vector>
20d86ed7fbStbbdev #include <algorithm> // std::max
21d86ed7fbStbbdev
22d86ed7fbStbbdev #include "oneapi/tbb/parallel_for.h"
23d86ed7fbStbbdev #include "oneapi/tbb/blocked_range.h"
24d86ed7fbStbbdev #include "oneapi/tbb/tick_count.h"
25d86ed7fbStbbdev
26d86ed7fbStbbdev static const std::size_t N = 22;
27d86ed7fbStbbdev
SerialSubStringFinder(const std::string & str,std::vector<std::size_t> & max_array,std::vector<std::size_t> & pos_array)28d86ed7fbStbbdev void SerialSubStringFinder(const std::string &str,
29d86ed7fbStbbdev std::vector<std::size_t> &max_array,
30d86ed7fbStbbdev std::vector<std::size_t> &pos_array) {
31d86ed7fbStbbdev for (std::size_t i = 0; i < str.size(); ++i) {
32d86ed7fbStbbdev std::size_t max_size = 0, max_pos = 0;
33d86ed7fbStbbdev for (std::size_t j = 0; j < str.size(); ++j)
34d86ed7fbStbbdev if (j != i) {
35d86ed7fbStbbdev std::size_t limit = str.size() - (std::max)(i, j);
36d86ed7fbStbbdev for (std::size_t k = 0; k < limit; ++k) {
37d86ed7fbStbbdev if (str[i + k] != str[j + k])
38d86ed7fbStbbdev break;
39d86ed7fbStbbdev if (k > max_size) {
40d86ed7fbStbbdev max_size = k;
41d86ed7fbStbbdev max_pos = j;
42d86ed7fbStbbdev }
43d86ed7fbStbbdev }
44d86ed7fbStbbdev }
45d86ed7fbStbbdev max_array[i] = max_size;
46d86ed7fbStbbdev pos_array[i] = max_pos;
47d86ed7fbStbbdev }
48d86ed7fbStbbdev }
49d86ed7fbStbbdev
50d86ed7fbStbbdev class SubStringFinder {
51d86ed7fbStbbdev const char *str;
52d86ed7fbStbbdev const std::size_t len;
53d86ed7fbStbbdev std::size_t *max_array;
54d86ed7fbStbbdev std::size_t *pos_array;
55d86ed7fbStbbdev
56d86ed7fbStbbdev public:
operator ()(const oneapi::tbb::blocked_range<std::size_t> & r) const57d86ed7fbStbbdev void operator()(const oneapi::tbb::blocked_range<std::size_t> &r) const {
58d86ed7fbStbbdev for (std::size_t i = r.begin(); i != r.end(); ++i) {
59d86ed7fbStbbdev std::size_t max_size = 0, max_pos = 0;
60d86ed7fbStbbdev for (std::size_t j = 0; j < len; ++j) {
61d86ed7fbStbbdev if (j != i) {
62d86ed7fbStbbdev std::size_t limit = len - (std::max)(i, j);
63d86ed7fbStbbdev for (std::size_t k = 0; k < limit; ++k) {
64d86ed7fbStbbdev if (str[i + k] != str[j + k])
65d86ed7fbStbbdev break;
66d86ed7fbStbbdev if (k > max_size) {
67d86ed7fbStbbdev max_size = k;
68d86ed7fbStbbdev max_pos = j;
69d86ed7fbStbbdev }
70d86ed7fbStbbdev }
71d86ed7fbStbbdev }
72d86ed7fbStbbdev }
73d86ed7fbStbbdev max_array[i] = max_size;
74d86ed7fbStbbdev pos_array[i] = max_pos;
75d86ed7fbStbbdev }
76d86ed7fbStbbdev }
77d86ed7fbStbbdev // We do not use std::vector for compatibility with offload execution
SubStringFinder(const char * s,const std::size_t s_len,std::size_t * m,std::size_t * p)78d86ed7fbStbbdev SubStringFinder(const char *s, const std::size_t s_len, std::size_t *m, std::size_t *p)
79d86ed7fbStbbdev : str(s),
80d86ed7fbStbbdev len(s_len),
81d86ed7fbStbbdev max_array(m),
82d86ed7fbStbbdev pos_array(p) {}
83d86ed7fbStbbdev };
84d86ed7fbStbbdev
main()85d86ed7fbStbbdev int main() {
86d86ed7fbStbbdev std::string str[N] = { std::string("a"), std::string("b") };
87d86ed7fbStbbdev for (std::size_t i = 2; i < N; ++i)
88d86ed7fbStbbdev str[i] = str[i - 1] + str[i - 2];
89d86ed7fbStbbdev std::string &to_scan = str[N - 1];
90d86ed7fbStbbdev const std::size_t num_elem = to_scan.size();
91d86ed7fbStbbdev
92d86ed7fbStbbdev std::vector<std::size_t> max1(num_elem);
93d86ed7fbStbbdev std::vector<std::size_t> pos1(num_elem);
94d86ed7fbStbbdev std::vector<std::size_t> max2(num_elem);
95d86ed7fbStbbdev std::vector<std::size_t> pos2(num_elem);
96d86ed7fbStbbdev
97d86ed7fbStbbdev std::cout << " Done building string."
98d86ed7fbStbbdev << "\n";
99d86ed7fbStbbdev
100d86ed7fbStbbdev oneapi::tbb::tick_count serial_t0 = oneapi::tbb::tick_count::now();
101d86ed7fbStbbdev SerialSubStringFinder(to_scan, max2, pos2);
102d86ed7fbStbbdev oneapi::tbb::tick_count serial_t1 = oneapi::tbb::tick_count::now();
103d86ed7fbStbbdev std::cout << " Done with serial version."
104d86ed7fbStbbdev << "\n";
105d86ed7fbStbbdev
106d86ed7fbStbbdev oneapi::tbb::tick_count parallel_t0 = oneapi::tbb::tick_count::now();
107d86ed7fbStbbdev oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<std::size_t>(0, num_elem, 100),
108d86ed7fbStbbdev SubStringFinder(to_scan.c_str(), num_elem, &max1[0], &pos1[0]));
109d86ed7fbStbbdev oneapi::tbb::tick_count parallel_t1 = oneapi::tbb::tick_count::now();
110d86ed7fbStbbdev std::cout << " Done with parallel version."
111d86ed7fbStbbdev << "\n";
112d86ed7fbStbbdev
113d86ed7fbStbbdev for (std::size_t i = 0; i < num_elem; ++i) {
114d86ed7fbStbbdev if (max1[i] != max2[i] || pos1[i] != pos2[i]) {
115d86ed7fbStbbdev std::cout << "ERROR: Serial and Parallel Results are Different!"
116d86ed7fbStbbdev << "\n";
117d86ed7fbStbbdev break;
118d86ed7fbStbbdev }
119d86ed7fbStbbdev }
120d86ed7fbStbbdev std::cout << " Done validating results."
121d86ed7fbStbbdev << "\n";
122d86ed7fbStbbdev
123d86ed7fbStbbdev std::cout << "Serial version ran in " << (serial_t1 - serial_t0).seconds() << " seconds"
124d86ed7fbStbbdev << "\n"
125d86ed7fbStbbdev << "Parallel version ran in " << (parallel_t1 - parallel_t0).seconds() << " seconds"
126d86ed7fbStbbdev << "\n"
127d86ed7fbStbbdev << "Resulting in a speedup of "
128d86ed7fbStbbdev << (serial_t1 - serial_t0).seconds() / (parallel_t1 - parallel_t0).seconds() << "\n";
129d86ed7fbStbbdev
130d86ed7fbStbbdev return 0;
131d86ed7fbStbbdev }
132