112590Sjason@lowepower.com/*
212590Sjason@lowepower.com * Copyright (c) 2017 Jason Lowe-Power
312590Sjason@lowepower.com* All rights reserved.
412590Sjason@lowepower.com*
512590Sjason@lowepower.com* Redistribution and use in source and binary forms, with or without
612590Sjason@lowepower.com* modification, are permitted provided that the following conditions are
712590Sjason@lowepower.com* met: redistributions of source code must retain the above copyright
812590Sjason@lowepower.com* notice, this list of conditions and the following disclaimer;
912590Sjason@lowepower.com* redistributions in binary form must reproduce the above copyright
1012590Sjason@lowepower.com* notice, this list of conditions and the following disclaimer in the
1112590Sjason@lowepower.com* documentation and/or other materials provided with the distribution;
1212590Sjason@lowepower.com* neither the name of the copyright holders nor the names of its
1312590Sjason@lowepower.com* contributors may be used to endorse or promote products derived from
1412590Sjason@lowepower.com* this software without specific prior written permission.
1512590Sjason@lowepower.com*
1612590Sjason@lowepower.com* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712590Sjason@lowepower.com* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812590Sjason@lowepower.com* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912590Sjason@lowepower.com* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012590Sjason@lowepower.com* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112590Sjason@lowepower.com* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212590Sjason@lowepower.com* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312590Sjason@lowepower.com* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412590Sjason@lowepower.com* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512590Sjason@lowepower.com* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612590Sjason@lowepower.com* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712590Sjason@lowepower.com*
2812590Sjason@lowepower.com* Authors: Jason Lowe-Power
2912590Sjason@lowepower.com*/
3012590Sjason@lowepower.com
3112590Sjason@lowepower.com#include <iostream>
3212590Sjason@lowepower.com#include <thread>
3312590Sjason@lowepower.com
3412590Sjason@lowepower.comusing namespace std;
3512590Sjason@lowepower.com
3612590Sjason@lowepower.com/*
3712590Sjason@lowepower.com * c = a + b
3812590Sjason@lowepower.com */
3912590Sjason@lowepower.comvoid array_add(int *a, int *b, int *c, int tid, int threads, int num_values)
4012590Sjason@lowepower.com{
4112590Sjason@lowepower.com    for (int i = tid; i < num_values; i += threads) {
4212590Sjason@lowepower.com        c[i] = a[i] + b[i];
4312590Sjason@lowepower.com    }
4412590Sjason@lowepower.com}
4512590Sjason@lowepower.com
4612590Sjason@lowepower.com
4712590Sjason@lowepower.comint main(int argc, char *argv[])
4812590Sjason@lowepower.com{
4912590Sjason@lowepower.com    unsigned num_values;
5012590Sjason@lowepower.com    if (argc == 1) {
5112590Sjason@lowepower.com        num_values = 100;
5212590Sjason@lowepower.com    } else if (argc == 2) {
5312590Sjason@lowepower.com        num_values = atoi(argv[1]);
5412590Sjason@lowepower.com        if (num_values <= 0) {
5512590Sjason@lowepower.com            cerr << "Usage: " << argv[0] << " [num_values]" << endl;
5612590Sjason@lowepower.com            return 1;
5712590Sjason@lowepower.com        }
5812590Sjason@lowepower.com    } else {
5912590Sjason@lowepower.com        cerr << "Usage: " << argv[0] << " [num_values]" << endl;
6012590Sjason@lowepower.com        return 1;
6112590Sjason@lowepower.com    }
6212590Sjason@lowepower.com
6312590Sjason@lowepower.com    unsigned cpus = thread::hardware_concurrency();
6412590Sjason@lowepower.com
6512590Sjason@lowepower.com    cout << "Running on " << cpus << " cores. ";
6612590Sjason@lowepower.com    cout << "with " << num_values << " values" << endl;
6712590Sjason@lowepower.com
6812590Sjason@lowepower.com    int *a, *b, *c;
6912590Sjason@lowepower.com    a = new int[num_values];
7012590Sjason@lowepower.com    b = new int[num_values];
7112590Sjason@lowepower.com    c = new int[num_values];
7212590Sjason@lowepower.com
7312590Sjason@lowepower.com    if (!(a && b && c)) {
7412590Sjason@lowepower.com        cerr << "Allocation error!" << endl;
7512590Sjason@lowepower.com        return 2;
7612590Sjason@lowepower.com    }
7712590Sjason@lowepower.com
7812590Sjason@lowepower.com    for (int i = 0; i < num_values; i++) {
7912590Sjason@lowepower.com        a[i] = i;
8012590Sjason@lowepower.com        b[i] = num_values - i;
8112590Sjason@lowepower.com        c[i] = 0;
8212590Sjason@lowepower.com    }
8312590Sjason@lowepower.com
8412590Sjason@lowepower.com    thread **threads = new thread*[cpus];
8512590Sjason@lowepower.com
8612590Sjason@lowepower.com    // NOTE: -1 is required for this to work in SE mode.
8712590Sjason@lowepower.com    for (int i = 0; i < cpus - 1; i++) {
8812590Sjason@lowepower.com        threads[i] = new thread(array_add, a, b, c, i, cpus, num_values);
8912590Sjason@lowepower.com    }
9012590Sjason@lowepower.com    // Execute the last thread with this thread context to appease SE mode
9112590Sjason@lowepower.com    array_add(a, b, c, cpus - 1, cpus, num_values);
9212590Sjason@lowepower.com
9312590Sjason@lowepower.com    cout << "Waiting for other threads to complete" << endl;
9412590Sjason@lowepower.com
9512590Sjason@lowepower.com    for (int i = 0; i < cpus - 1; i++) {
9612590Sjason@lowepower.com        threads[i]->join();
9712590Sjason@lowepower.com    }
9812590Sjason@lowepower.com
9912590Sjason@lowepower.com    delete[] threads;
10012590Sjason@lowepower.com
10112590Sjason@lowepower.com    cout << "Validating..." << flush;
10212590Sjason@lowepower.com
10312590Sjason@lowepower.com    int num_valid = 0;
10412590Sjason@lowepower.com    for (int i = 0; i < num_values; i++) {
10512590Sjason@lowepower.com        if (c[i] == num_values) {
10612590Sjason@lowepower.com            num_valid++;
10712590Sjason@lowepower.com        } else {
10812590Sjason@lowepower.com            cerr << "c[" << i << "] is wrong.";
10912590Sjason@lowepower.com            cerr << " Expected " << num_values;
11012590Sjason@lowepower.com            cerr << " Got " << c[i] << "." << endl;
11112590Sjason@lowepower.com        }
11212590Sjason@lowepower.com    }
11312590Sjason@lowepower.com
11412590Sjason@lowepower.com    if (num_valid == num_values) {
11512590Sjason@lowepower.com        cout << "Success!" << endl;
11612590Sjason@lowepower.com        return 0;
11712590Sjason@lowepower.com    } else {
11812590Sjason@lowepower.com        return 2;
11912590Sjason@lowepower.com    }
12012590Sjason@lowepower.com}
121