Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ This repository is intended as:

Examples include (and will expand to):

* [thread-safe-queue](./thread-safe-queue/)
* Multithreading
* [thread-safe-queue](./thread-safe-queue/)
* [multithread-sum](./multithread-sum/)
* Smart pointers
* [unique-ptr-basics](./unique-ptr-basics/)
* [smart-ptr](./smart-ptr/)
Expand Down
30 changes: 30 additions & 0 deletions multithread-sum/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# pull in shared compiler settings
include ../common.mk

# per-example flags
# CXXFLAGS += -pthread

## get it from the folder name
TARGET := $(notdir $(CURDIR))
SRCS := $(wildcard *.cpp)
OBJS := $(SRCS:.cpp=.o)

all: $(TARGET)

$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $@ $^

%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@

run: $(TARGET)
./$(TARGET) $(ARGS)

clean:
rm -f $(OBJS) $(TARGET)

# Delegates to top-level Makefile
check-format:
$(MAKE) -f ../Makefile check-format DIR=$(CURDIR)

.PHONY: all clean run check-format
88 changes: 88 additions & 0 deletions multithread-sum/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
This demonstrates a simple multithreaded sum calculation using C++11 threads.
*/

#include <cassert>
#include <iostream>
#include <vector>
#include <thread>
#include <numeric>
#include <stdexcept> // for exceptions
#include <limits>

using SumT = unsigned long long;

int
main(int argc, char* argv[])
{
std::size_t data_size = 1'000'000;
std::size_t num_threads = 4;

if (argc == 3) {
try {
long long ds = std::stoll(argv[1]);
long long nt = std::stoll(argv[2]);
if (ds < 0 || nt <= 0) {
throw std::invalid_argument("data_size must be >= 0 and num_threads must be > 0");
}
data_size = static_cast<std::size_t>(ds);
num_threads = static_cast<std::size_t>(nt);
} catch (const std::exception& e) {
std::cerr << "Invalid arguments: " << e.what() << "\n"
<< "Usage: " << argv[0] << " <data_size> <num_threads>\n";
return 1;
}
} else if (argc != 1) {
std::cerr << "Usage: " << argv[0] << " <data_size> <num_threads>\n";
return 1;
}

if (num_threads == 0)
return 1;
if (data_size == 0) {
std::cout << "Total Sum: 0\nExpected Sum: 0\n";
return 0;
}

// Avoid spawning more threads than elements (optional but sensible).
if (num_threads > data_size)
num_threads = data_size;

// Guard against int overflow in iota values.
if (data_size > static_cast<std::size_t>(std::numeric_limits<int>::max())) {
std::cerr << "data_size too large for vector<int> initialization via iota.\n";
return 1;
}

std::vector<int> data(data_size);
std::iota(data.begin(), data.end(), 1);

std::vector<SumT> partial_sums(num_threads, 0);
std::vector<std::thread> threads;
threads.reserve(num_threads);

const std::size_t block_size = data_size / num_threads;

for (std::size_t i = 0; i < num_threads; ++i) {
const std::size_t start = i * block_size;
const std::size_t end = (i == num_threads - 1) ? data_size : start + block_size;

threads.emplace_back([&, i, start, end] {
partial_sums[i] = std::accumulate(data.begin() + start, data.begin() + end, SumT{0});
std::cout << "Thread processing range [" << start << ", " << end
<< ") computed local sum: " << partial_sums[i] << "\n";
});
}

for (auto& t : threads)
t.join();

const SumT global_sum = std::accumulate(partial_sums.begin(), partial_sums.end(), SumT{0});
std::cout << "Total Sum: " << global_sum << "\n";

const SumT expected_sum = static_cast<SumT>(data_size) * (static_cast<SumT>(data_size) + 1) / 2;
std::cout << "Expected Sum: " << expected_sum << "\n";

assert(expected_sum == global_sum);
return 0;
}
5 changes: 5 additions & 0 deletions multithread-sum/tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

set -ex

./multithread-sum 1000000 4