Solved exc1
This commit is contained in:
14
.vscode/settings.json
vendored
14
.vscode/settings.json
vendored
@@ -68,6 +68,18 @@
|
||||
"set": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"xhash": "cpp",
|
||||
"xtree": "cpp"
|
||||
"xtree": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"map": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"string_view": "cpp",
|
||||
"numbers": "cpp",
|
||||
"semaphore": "cpp",
|
||||
"cinttypes": "cpp"
|
||||
}
|
||||
}
|
||||
69
lab12/exc1/plot_sieve_results.py
Normal file
69
lab12/exc1/plot_sieve_results.py
Normal file
@@ -0,0 +1,69 @@
|
||||
import os
|
||||
import re
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def parse_result_files(fixed_N, directory="."):
|
||||
pattern = re.compile(r"runtime_p_(\d+)_N_({})\.txt".format(fixed_N))
|
||||
results = []
|
||||
|
||||
for filename in os.listdir(directory):
|
||||
match = pattern.match(filename)
|
||||
if match:
|
||||
p = int(match.group(1))
|
||||
with open(os.path.join(directory, filename), "r") as f:
|
||||
line = f.readline().strip()
|
||||
time_str, N_str = line.split(",")
|
||||
time = float(time_str)
|
||||
results.append((p, time))
|
||||
|
||||
results.sort(key=lambda x: x[0]) # sort by number of processes
|
||||
return results
|
||||
|
||||
def plot_results(results, N, output_file="sieve_scaling_plot.png"):
|
||||
ps = [p for p, _ in results]
|
||||
times = [t for _, t in results]
|
||||
|
||||
performance = [N / t for t in times]
|
||||
speedup = [times[0] / t for t in times]
|
||||
efficiency = [s / p for s, p in zip(speedup, ps)]
|
||||
|
||||
plt.figure(figsize=(12, 8))
|
||||
|
||||
# Performance plot
|
||||
plt.subplot(3, 1, 1)
|
||||
plt.plot(ps, performance, marker='o')
|
||||
plt.title(f"Performance (N = {N})")
|
||||
plt.xlabel("Processes")
|
||||
plt.ylabel("Performance (N / time)")
|
||||
|
||||
# Speedup plot
|
||||
plt.subplot(3, 1, 2)
|
||||
plt.plot(ps, speedup, marker='o')
|
||||
plt.title("Speedup")
|
||||
plt.xlabel("Processes")
|
||||
plt.ylabel("Speedup (T1 / Tp)")
|
||||
|
||||
# Efficiency plot
|
||||
plt.subplot(3, 1, 3)
|
||||
plt.plot(ps, efficiency, marker='o')
|
||||
plt.title("Efficiency")
|
||||
plt.xlabel("Processes")
|
||||
plt.ylabel("Efficiency (Speedup / p)")
|
||||
|
||||
plt.tight_layout()
|
||||
plt.savefig(output_file)
|
||||
print(f"Plot saved to: {output_file}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("N", type=int, help="Fixed N to plot results for")
|
||||
parser.add_argument("--dir", type=str, default=".", help="Directory with result files")
|
||||
parser.add_argument("--out", type=str, default="sieve_scaling_plot.png", help="Output image file")
|
||||
args = parser.parse_args()
|
||||
|
||||
data = parse_result_files(args.N, args.dir)
|
||||
if not data:
|
||||
print(f"No matching files found for N = {args.N}")
|
||||
else:
|
||||
plot_results(data, args.N, args.out)
|
||||
1
lab12/exc1/primes_100.txt
Normal file
1
lab12/exc1/primes_100.txt
Normal file
@@ -0,0 +1 @@
|
||||
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,
|
||||
1
lab12/exc1/primes_1000.txt
Normal file
1
lab12/exc1/primes_1000.txt
Normal file
@@ -0,0 +1 @@
|
||||
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,
|
||||
1
lab12/exc1/primes_1000000.txt
Normal file
1
lab12/exc1/primes_1000000.txt
Normal file
File diff suppressed because one or more lines are too long
1
lab12/exc1/primes_100000000.txt
Normal file
1
lab12/exc1/primes_100000000.txt
Normal file
File diff suppressed because one or more lines are too long
1
lab12/exc1/runtime_p_1_N_1000000.txt
Normal file
1
lab12/exc1/runtime_p_1_N_1000000.txt
Normal file
@@ -0,0 +1 @@
|
||||
0.232095,1000000
|
||||
1
lab12/exc1/runtime_p_2_N_1000000.txt
Normal file
1
lab12/exc1/runtime_p_2_N_1000000.txt
Normal file
@@ -0,0 +1 @@
|
||||
0.121674,1000000
|
||||
1
lab12/exc1/runtime_p_3_N_1000000.txt
Normal file
1
lab12/exc1/runtime_p_3_N_1000000.txt
Normal file
@@ -0,0 +1 @@
|
||||
0.0957458,1000000
|
||||
1
lab12/exc1/runtime_p_4_N_100.txt
Normal file
1
lab12/exc1/runtime_p_4_N_100.txt
Normal file
@@ -0,0 +1 @@
|
||||
0.0001227,100
|
||||
1
lab12/exc1/runtime_p_4_N_1000.txt
Normal file
1
lab12/exc1/runtime_p_4_N_1000.txt
Normal file
@@ -0,0 +1 @@
|
||||
0.0001636,1000
|
||||
1
lab12/exc1/runtime_p_4_N_1000000.txt
Normal file
1
lab12/exc1/runtime_p_4_N_1000000.txt
Normal file
@@ -0,0 +1 @@
|
||||
0.07924,1000000
|
||||
1
lab12/exc1/runtime_p_4_N_100000000.txt
Normal file
1
lab12/exc1/runtime_p_4_N_100000000.txt
Normal file
@@ -0,0 +1 @@
|
||||
42.6024,100000000
|
||||
164
lab12/exc1/sieve_e.cpp
Normal file
164
lab12/exc1/sieve_e.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <mpi.h>
|
||||
#include <limits>
|
||||
#include <fstream>
|
||||
|
||||
std::vector<int> get_start_condition(int N, int count_proc, int rank)
|
||||
{
|
||||
int total_elements = N - 1;
|
||||
int base_chunk = total_elements / count_proc;
|
||||
int remainder = total_elements % count_proc;
|
||||
|
||||
int start_offset = rank * base_chunk + std::min(rank, remainder);
|
||||
int chunk_size = base_chunk + (rank < remainder ? 1 : 0);
|
||||
|
||||
int start = 2 + start_offset;
|
||||
int end = start + chunk_size;
|
||||
|
||||
std::vector<int> start_set;
|
||||
for (int i = start; i < end; ++i)
|
||||
{
|
||||
if (i == 2 || i % 2 == 1)
|
||||
start_set.emplace_back(i);
|
||||
}
|
||||
|
||||
return start_set;
|
||||
}
|
||||
|
||||
// mark element as not prim by setting to 0
|
||||
// point out next k while sieving
|
||||
int sieve(std::vector<int> &set, int k)
|
||||
{
|
||||
bool next_k_set = false;
|
||||
int next_k = k;
|
||||
for (int &elem : set)
|
||||
{
|
||||
if ((elem > k) && (elem != 0))
|
||||
{
|
||||
if (!next_k_set)
|
||||
{
|
||||
next_k = elem;
|
||||
next_k_set = true;
|
||||
}
|
||||
if (elem % k == 0)
|
||||
{
|
||||
elem = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return next_k;
|
||||
}
|
||||
|
||||
void print_vec(std::vector<int> vec)
|
||||
{
|
||||
for (int elem : vec)
|
||||
{
|
||||
std::cout << elem << ", ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void save_result_to_file(std::vector<int> vec, int N)
|
||||
{
|
||||
std::ofstream outfile("primes_" + std::to_string(N) + ".txt");
|
||||
for (int val : vec)
|
||||
{
|
||||
outfile << val << ",";
|
||||
}
|
||||
outfile << std::endl;
|
||||
outfile.close();
|
||||
}
|
||||
|
||||
void save_runtime_to_file(double runtime, int N, int numProc)
|
||||
{
|
||||
std::ofstream outfile("runtime_p_" + std::to_string(numProc) + "_N_" + std::to_string(N) + ".txt");
|
||||
outfile << runtime << "," << N;
|
||||
outfile << std::endl;
|
||||
outfile.close();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
MPI_Init(&argc, &argv);
|
||||
double start_time = MPI_Wtime();
|
||||
int N = atoi(argv[1]);
|
||||
int numProc, rank;
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &numProc);
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
|
||||
std::vector<int> list_to_sieve = get_start_condition(N, numProc, rank);
|
||||
|
||||
int k = 2;
|
||||
int global_min_k = 0;
|
||||
int local_max_N = list_to_sieve[list_to_sieve.size() - 1];
|
||||
while (true)
|
||||
{
|
||||
int offered_k = (k < local_max_N) ? sieve(list_to_sieve, k) : std::numeric_limits<int>::max();
|
||||
|
||||
MPI_Allreduce(&offered_k, &global_min_k, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
|
||||
|
||||
if (global_min_k * global_min_k >= N)
|
||||
break;
|
||||
|
||||
k = global_min_k;
|
||||
}
|
||||
|
||||
std::vector<int> recvcounts(numProc);
|
||||
std::vector<int> displs(numProc);
|
||||
|
||||
int local_size = list_to_sieve.size();
|
||||
std::vector<int> final_results(numProc * local_size);
|
||||
|
||||
// 1. Share local sizes from all ranks to rank 0
|
||||
MPI_Gather(&local_size, 1, MPI_INT,
|
||||
recvcounts.data(), 1, MPI_INT,
|
||||
0, MPI_COMM_WORLD);
|
||||
|
||||
// 2. Calculate displacements on rank 0
|
||||
if (rank == 0)
|
||||
{
|
||||
displs[0] = 0;
|
||||
for (int i = 1; i < numProc; ++i)
|
||||
{
|
||||
displs[i] = displs[i - 1] + recvcounts[i - 1];
|
||||
}
|
||||
|
||||
// Resize final_results based on total size
|
||||
int total = displs[numProc - 1] + recvcounts[numProc - 1];
|
||||
final_results.resize(total);
|
||||
}
|
||||
|
||||
if (rank == 0)
|
||||
{
|
||||
std::copy(list_to_sieve.begin(), list_to_sieve.end(), final_results.begin());
|
||||
MPI_Gatherv(MPI_IN_PLACE, local_size, MPI_INT,
|
||||
final_results.data(), recvcounts.data(), displs.data(), MPI_INT,
|
||||
0, MPI_COMM_WORLD);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
MPI_Gatherv(list_to_sieve.data(), local_size, MPI_INT,
|
||||
nullptr, nullptr, nullptr, MPI_INT,
|
||||
0, MPI_COMM_WORLD);
|
||||
}
|
||||
|
||||
double end_time = MPI_Wtime();
|
||||
double elapsed = end_time - start_time;
|
||||
|
||||
if (rank == 0)
|
||||
{
|
||||
std::vector<int> non_zero_results;
|
||||
for (int val : final_results)
|
||||
{
|
||||
if (val != 0)
|
||||
non_zero_results.push_back(val);
|
||||
}
|
||||
|
||||
save_result_to_file(non_zero_results, N);
|
||||
save_runtime_to_file(elapsed, N, numProc);
|
||||
}
|
||||
|
||||
MPI_Finalize();
|
||||
return 0;
|
||||
}
|
||||
BIN
lab12/exc1/sieve_scaling_plot.png
Normal file
BIN
lab12/exc1/sieve_scaling_plot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
@@ -1,67 +0,0 @@
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <mpi.h>
|
||||
|
||||
std::vector<int> get_start_condition(int N, int count_proc, int rank)
|
||||
{
|
||||
int total_elements = N - 1; // because range starts at 2
|
||||
int base_chunk = total_elements / count_proc;
|
||||
int remainder = total_elements % count_proc;
|
||||
|
||||
int start_offset = rank * base_chunk + std::min(rank, remainder);
|
||||
int chunk_size = base_chunk + (rank < remainder ? 1 : 0);
|
||||
|
||||
int start = 2 + start_offset;
|
||||
int end = start + chunk_size; // exclusive
|
||||
|
||||
std::vector<int> start_set;
|
||||
for (int i = start; i < end; ++i)
|
||||
{
|
||||
start_set.emplace_back(i);
|
||||
}
|
||||
|
||||
return start_set;
|
||||
}
|
||||
|
||||
|
||||
// mark element as not prim by setting to 0
|
||||
|
||||
// 2,3,4
|
||||
// 0,1,2
|
||||
// even numbers are at even indices
|
||||
// index is (number - 2) or (number - start)
|
||||
|
||||
void sieve(std::vector<int> &set, int k)
|
||||
{
|
||||
for (int &elem : set)
|
||||
{
|
||||
if ((elem != k) && (elem != 0) && (elem % k == 0))
|
||||
{
|
||||
elem = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_vec(std::vector<int> vec)
|
||||
{
|
||||
for (int elem : vec)
|
||||
{
|
||||
std::cout << elem << ", ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// MPI_Init(&argc, &argv);
|
||||
int procs = atoi(argv[1]);
|
||||
int N = atoi(argv[2]);
|
||||
std::cout << "Procs: " << procs << " N: " << N << std::endl;
|
||||
for (int proc = 0; proc < procs; proc++)
|
||||
{
|
||||
std::vector<int> elems = get_start_condition(N, procs, proc);
|
||||
print_vec(elems);
|
||||
}
|
||||
|
||||
// MPI_Finalize();
|
||||
}
|
||||
Reference in New Issue
Block a user