initial commit
This commit is contained in:
commit
8a436fe8d4
36
Dockerfile
Normal file
36
Dockerfile
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
FROM debian:stable-slim
|
||||||
|
|
||||||
|
# Install g++, make, OpenMPI, AND the OpenSSH server
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
g++ \
|
||||||
|
make \
|
||||||
|
openmpi-bin \
|
||||||
|
libopenmpi-dev \
|
||||||
|
openssh-server && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Create a directory for the SSH daemon to run (use -p to avoid errors)
|
||||||
|
RUN mkdir -p /var/run/sshd
|
||||||
|
|
||||||
|
# --- SSH Key Generation and Configuration ---
|
||||||
|
# Generate a passwordless SSH key pair
|
||||||
|
RUN ssh-keygen -t rsa -f /root/.ssh/id_rsa -N ''
|
||||||
|
|
||||||
|
# Add the public key to the list of authorized keys for passwordless login
|
||||||
|
RUN cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
|
||||||
|
RUN chmod 600 /root/.ssh/authorized_keys
|
||||||
|
|
||||||
|
# --- THIS IS THE NEW LINE ---
|
||||||
|
# Create an SSH config file to disable host key checking
|
||||||
|
RUN echo "Host *\n\tStrictHostKeyChecking no" >> /root/.ssh/config
|
||||||
|
# --- END OF NEW LINE ---
|
||||||
|
|
||||||
|
# Allow root login via SSH
|
||||||
|
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY . /app/
|
||||||
|
|
||||||
|
# Compile using the MPI C++ compiler wrapper
|
||||||
|
RUN mpic++ -O2 -std=c++17 -o mpi_task task.cpp
|
||||||
35
docker-compose.yml
Normal file
35
docker-compose.yml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
services:
|
||||||
|
master:
|
||||||
|
build: .
|
||||||
|
container_name: pdc-master
|
||||||
|
volumes:
|
||||||
|
- ./hostfile:/app/hostfile
|
||||||
|
command: >
|
||||||
|
sh -c "/usr/sbin/sshd & sleep 5 && mpirun -np 4 --hostfile /app/hostfile --allow-run-as-root /app/mpi_task"
|
||||||
|
networks:
|
||||||
|
- pdcn
|
||||||
|
|
||||||
|
worker1:
|
||||||
|
build: .
|
||||||
|
container_name: pdc-worker1
|
||||||
|
command: /usr/sbin/sshd -D
|
||||||
|
networks:
|
||||||
|
- pdcn
|
||||||
|
|
||||||
|
worker2:
|
||||||
|
build: .
|
||||||
|
container_name: pdc-worker2
|
||||||
|
command: /usr/sbin/sshd -D
|
||||||
|
networks:
|
||||||
|
- pdcn
|
||||||
|
|
||||||
|
worker3:
|
||||||
|
build: .
|
||||||
|
container_name: pdc-worker3
|
||||||
|
command: /usr/sbin/sshd -D
|
||||||
|
networks:
|
||||||
|
- pdcn
|
||||||
|
|
||||||
|
networks:
|
||||||
|
pdcn:
|
||||||
|
driver: bridge
|
||||||
4
hostfile
Normal file
4
hostfile
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
master slots=1
|
||||||
|
worker1 slots=1
|
||||||
|
worker2 slots=1
|
||||||
|
worker3 slots=1
|
||||||
67
task.cpp
Normal file
67
task.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <mpi.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
MPI_Init(&argc, &argv);
|
||||||
|
|
||||||
|
int world_size;
|
||||||
|
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
|
||||||
|
|
||||||
|
int world_rank;
|
||||||
|
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
|
||||||
|
|
||||||
|
if (world_rank == 0) {
|
||||||
|
// Master process
|
||||||
|
std::string message = "HELLOWORLDFROMMPI"; // A longer string to see the effect
|
||||||
|
std::cout << "Original Message: " << message << std::endl;
|
||||||
|
std::cout << "Total processes (world size): " << world_size << std::endl;
|
||||||
|
|
||||||
|
int msg_len = message.length();
|
||||||
|
int part_size = msg_len / world_size;
|
||||||
|
|
||||||
|
// Send each worker its part of the string
|
||||||
|
for (int i = 1; i < world_size; ++i) {
|
||||||
|
int start_index = i * part_size;
|
||||||
|
// The last worker gets any remaining characters
|
||||||
|
int current_part_size = (i == world_size - 1) ? (msg_len - start_index) : part_size;
|
||||||
|
std::string part = message.substr(start_index, current_part_size);
|
||||||
|
MPI_Send(part.c_str(), part.size() + 1, MPI_CHAR, i, 0, MPI_COMM_WORLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Master processes its own part
|
||||||
|
std::string master_part = message.substr(0, part_size);
|
||||||
|
std::reverse(master_part.begin(), master_part.end());
|
||||||
|
|
||||||
|
// A vector to store results in order
|
||||||
|
std::vector<std::string> results(world_size);
|
||||||
|
results[0] = master_part;
|
||||||
|
|
||||||
|
// Receive reversed parts from workers
|
||||||
|
for (int i = 1; i < world_size; ++i) {
|
||||||
|
char buffer[256];
|
||||||
|
MPI_Recv(buffer, 256, MPI_CHAR, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
|
||||||
|
results[i] = std::string(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine and print the final result
|
||||||
|
std::string final_result = "";
|
||||||
|
for (int i = 0; i < world_size; ++i) {
|
||||||
|
final_result += results[i];
|
||||||
|
}
|
||||||
|
std::cout << "Final Result: " << final_result << std::endl;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Worker processes
|
||||||
|
char buffer[256];
|
||||||
|
MPI_Recv(buffer, 256, MPI_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
|
||||||
|
std::string part(buffer);
|
||||||
|
std::reverse(part.begin(), part.end());
|
||||||
|
MPI_Send(part.c_str(), part.size() + 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
MPI_Finalize();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user