This commit is contained in:
Michael Zhang 2023-11-19 06:57:10 +00:00
parent 7793d5b447
commit 09da2cf70a
14 changed files with 1656614 additions and 11 deletions

View file

@ -24,7 +24,8 @@
"ms-vscode.makefile-tools",
"rust-lang.rust-analyzer",
"tomoki1207.pdf",
"nvarner.typst-lsp"
"nvarner.typst-lsp",
"tamasfe.even-better-toml"
]
}
}

412
Cargo.lock generated
View file

@ -2,6 +2,15 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]]
name = "anstream"
version = "0.6.4"
@ -56,12 +65,78 @@ version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "assignment-03"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"mpi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bindgen"
version = "0.68.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn",
"which",
]
[[package]]
name = "bitflags"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
[[package]]
name = "build-probe-mpi"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6606c78346df2f2e1f39ac51d0a7752060a08a5de7805f0ad1b3bbefa93be8cc"
dependencies = [
"pkg-config",
"shell-words",
]
[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -69,10 +144,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.4.6"
name = "clang-sys"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956"
checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "4.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64"
dependencies = [
"clap_builder",
"clap_derive",
@ -80,9 +166,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.4.6"
version = "4.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45"
checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc"
dependencies = [
"anstream",
"anstyle",
@ -92,9 +178,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.4.2"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
dependencies = [
"heck",
"proc-macro2",
@ -104,9 +190,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.5.1"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "colorchoice"
@ -114,6 +200,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "conv"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
dependencies = [
"custom_derive",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.3"
@ -147,18 +242,49 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "custom_derive"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9"
[[package]]
name = "either"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "errno"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "home"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
dependencies = [
"windows-sys",
]
[[package]]
name = "itertools"
version = "0.11.0"
@ -168,6 +294,71 @@ dependencies = [
"either",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]]
name = "libffi"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2"
dependencies = [
"libc",
"libffi-sys",
]
[[package]]
name = "libffi-sys"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c"
dependencies = [
"cc",
]
[[package]]
name = "libloading"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [
"cfg-if",
"winapi",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829"
[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "memchr"
version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "memoffset"
version = "0.9.0"
@ -177,6 +368,89 @@ dependencies = [
"autocfg",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "mpi"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feff046b021e89291acbb509336cd0a9fec3c0ccb54d996401bcb35b8bbf267a"
dependencies = [
"build-probe-mpi",
"conv",
"libffi",
"memoffset",
"mpi-derive",
"mpi-sys",
"once_cell",
"smallvec",
"thiserror",
]
[[package]]
name = "mpi-derive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afac052fc749ada64568058c82fcb835bcba21a10453cdc5357c8385f055e657"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "mpi-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cb5d935a63f2c1c7b4f41dcf897869efb1b5ce8e48019b982a43fff2c34b916"
dependencies = [
"bindgen",
"build-probe-mpi",
"cc",
]
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "pkg-config"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "prettyplease"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.67"
@ -215,6 +489,35 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "regex"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rust"
version = "0.1.0"
@ -225,12 +528,49 @@ dependencies = [
"rayon",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.38.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "shell-words"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
[[package]]
name = "shlex"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
[[package]]
name = "smallvec"
version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]]
name = "strsim"
version = "0.10.0"
@ -248,6 +588,26 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
@ -260,6 +620,40 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.48.0"

View file

@ -1,3 +1,6 @@
[workspace]
resolver = "2"
members = ["assignments/01/rust"]
members = [
"assignments/01/rust",
"assignments/03/rust",
]

View file

@ -9,6 +9,7 @@ RUN apt update -y && apt install -y --no-install-recommends \
build-essential \
ca-certificates \
clangd \
clang \
curl \
direnv \
git \
@ -28,4 +29,6 @@ RUN pip install poetry
COPY --from=typst /bin/typst /usr/bin/typst
RUN curl https://sh.rustup.rs -sSf | bash -s -- -y
RUN /root/.cargo/bin/cargo install cargo-watch
RUN echo 'eval "$(direnv hook bash)"' >> /root/.bashrc

View file

@ -0,0 +1,140 @@
## Introduction
The purpose of this assignment is to become familiar with unstructured and input data instance dependent communication patterns by developing a parallel connected-component algorithm using label propagation in MPI. This is a non-trivial programming assignment so you need to start thinking and working on it as soon as possible.
You need to write a program that will takes as input one file, a graph G and outputs the connected components of the graph, i.e., the vertex labels identifying the component to which each vertex belongs. The input file for the graph will consist of a set of (i j) space-separated tuples (each on its own line) corresponding to the edges of the graph. You can assume that the input files are sorted in increasing (i, j) order.
Here is the output function you should use:
```c
/**
* @brief Write a vector of labels to a file.
*
* @param filename The name of the file to write to.
* @param labels The array of labels.
* @param nlabels How many labels to write.
*/
static void print_labels(
char const * const filename,
unsigned const * const labels,
size_t const nlabels)
{
size_t i;
FILE * fout;
/* open file */
if((fout = fopen(filename, "w")) == NULL) {
fprintf(stderr, "error opening '%s'\n", filename);
abort();
}
/* write labels to fout */
for(i = 0; i < nlabels; ++i) {
fprintf(fout, "%u\n", labels[i]);
}
fclose(fout);
}
```
## Parallelization strategy
Design your programs so that they follow the following steps:
1. One process reads the file and distributes the data to the other processes using a 1D decomposition (each rank gets approx same number of vertices). You should take care to perform this decomposition using consecutive vertices (i.e. if there are two processes and 60 vertices, then proc. 1 should be responsible the first 30 vertices and proc. 2 should be responsible the second 30 vertices). Not performing a 1D decomposition in this way will result in large increases in your timings.
2. Each process analyzes the non-local edges that are contained in its portion of the graph.
3. Each process determines which processors stores the non-local vertices corresponding to the non-local edges.
4. All the processes are communicating to figure out which process needs to send what data to the other processes.
5. The processes perform the transfers of non-local labels and updates of local labels until convergence.
6. The results are gathered to a single process, which writes them to the disk.
```
initialization by assigning a unique label to each node in G
pre-compute the unstructured communication information
while not converged, (convergence means NO node changes its label)
exchange non-local labels
for each local node n
assign the new label of n to be the maximum label of its neighbors (local and non-local)
```
Please make sure that you design your data structures in such a way so that accessing the received non-local labels does not cost any more than the time required to access your local labels. Also, your solution should be memory scalable (i.e., allocating a label vector of size n is not an option). You should be using exactly as much memory as required to store the labels that you need to compute the connected components.
## Testing
A few test graphs are available on the csel-plate machines at /export/scratch/CSCI5451_F23/assignment-3/dataset. The input files are organized such that the first line contains the number of nodes and the number of edges (space separated). The following lines contain the edges of the graph. The graphs are undirected (i.e., if (i, j) is present in the input file, then (j, i) will be present as well). The graphs also do not contain any self-referential edges (i.e., there is no i such that (i, i) is in our input file). Finally, the file names indicate the number of vertices in the graph (i.e., 12.txt has 12 vertices). There are 50 components for 1000.txt, 500 components for both 10000.txt and 100000.txt, 5000 components for 1000000.txt.
Your file output should contain n lines-each line should contain the component label for node i on the i-th line. As an example, if we have 4 nodes with 2 edges of (0, 1) and (2, 3), then your file output, using the above algorithm, should be as follows.
```
1
1
3
3
```
## Timing
Use the function MPI_Wtime() to time sections of your source code. You should provide times for steps 2-5 and also times for steps 5. You must use barriers before timers are started and ended to ensure accurate timing results. For your timings, it is very important that you only exchange the needed label information between processes. Exchanging more label information than is necessary will result in large increases in runtime on the provided test graph.
You should use this function to print your times:
```c
/**
* @brief Output the seconds elapsed steps 2-5. This excludes input and
* output time. This should be wallclock time, not CPU time.
*
* @param seconds Seconds spent sorting.
*/
static void print_time25(
double const seconds)
{
printf("2-5 Time: %0.04fs\n", seconds);
}
```
```c
/**
* @brief Output the seconds elapsed for step 5. This excludes input and
* output time. This should be wallclock time, not CPU time.
*
* @param seconds Seconds spent sorting.
*/
static void print_time5(
double const seconds)
{
printf("5 Time: %0.04fs\n", seconds);
}
```
## What you need to turn in
1. The source code of your program. Your major source file (containing the main function and all MPI calls) should be named lpa.c.
2. A short writeup describing how you went about solving steps 2-5. For step 5, describe how your label propagation code accesses the non-local labels that it received.
3. Timing results on 1, 2, 4, 8, & 16 processors for performing the steps 2-5 above for graph 100000.txt. (100,000 vertices)
4. Timing results for just step 5 above on 100000.txt. (100,000 vertices)
Please, do NOT include the test files.
## Code Submission Guidelines
1. A makefile must be provided to compile and generate the executable, which must be named lpa
2. The first line of the output must be the total time taken (steps 2-5) followed by time taken for step 5. Use the provided functions.
3. Your program should be invoked via:
```
mpirun -np 8 ./lpa <graph> <labels>
```
4. The report must be named report.pdf.
5. All files (Code + Report) must be in a single directory and directory's name should be your University Student ID.
6. Submission must be only .tar.gz files.
## Evaluation criteria
Here are the criteria that you will be graded on:
1. Efficiency in performing each one of the steps.
2. Low memory complexity.
3. Speedup. I will like to evaluate the speedup for performing steps 2-5 and also for step 5.

1416
assignments/03/dataset/1000.txt Executable file

File diff suppressed because it is too large Load diff

14123
assignments/03/dataset/10000.txt Executable file

File diff suppressed because it is too large Load diff

149132
assignments/03/dataset/100000.txt Executable file

File diff suppressed because it is too large Load diff

1491267
assignments/03/dataset/1000000.txt Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,3 @@
4 2
0 1
2 3

1
assignments/03/lpa.c Normal file
View file

@ -0,0 +1 @@
int main() {}

View file

@ -0,0 +1,11 @@
[package]
name = "assignment-03"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.75"
clap = { version = "4.4.8", features = ["derive"] }
mpi = { version = "0.7.0", features = ["derive"] }

View file

@ -0,0 +1,109 @@
use std::{
fs::File,
io::{BufRead, BufReader},
path::PathBuf,
};
use anyhow::Result;
use clap::Parser;
use mpi::{
datatype::Partition,
traits::{Communicator, Equivalence, Root},
Count,
};
#[derive(Debug, Parser)]
struct Opt {
graph_file: PathBuf,
label_file: PathBuf,
}
fn main() -> Result<()> {
let universe = mpi::initialize().unwrap();
let world = universe.world();
let size = world.size();
let rank = world.rank();
let size_u = size as usize;
let rank_u = rank as usize;
let root_rank = 0;
let root_process = world.process_at_rank(root_rank);
let opt = Opt::parse();
// One process reads the file and distributes the data to the other processes
// using a 1D decomposition (each rank gets approx same number of vertices).
let mut this_process_edges = Vec::<Edge>::new();
if rank == root_rank {
let file = File::open(opt.graph_file)?;
let mut reader = BufReader::new(file);
let mut line = String::new();
reader.read_line(&mut line)?;
let parts = line.trim().split_ascii_whitespace().collect::<Vec<_>>();
let num_nodes: usize = parts[0].parse()?;
let num_edges: usize = parts[1].parse()?;
let mut edges = Vec::with_capacity(num_edges);
for _ in 0..num_edges {
reader.read_line(&mut line)?;
let parts = line.trim().split_ascii_whitespace().collect::<Vec<_>>();
let from_node: usize = parts[0].parse()?;
let to_node: usize = parts[0].parse()?;
let edge = Edge { from_node, to_node };
edges.push(edge);
}
let edges = edges;
let mut counts = Vec::with_capacity(size_u);
let mut displs = Vec::with_capacity(size_u);
let step = num_edges / size_u;
for (process, idx) in (0..size_u).enumerate() {
let start = idx * step;
let end = if process == size_u - 1 {
num_edges
} else {
start + step
};
let this_process_num_edges = end - start;
println!(
"[{process}/{size}] shiet {start}..{end} ({this_process_num_edges})"
);
counts.push(this_process_num_edges as Count);
displs.push(start as Count);
}
let partition =
Partition::<[Edge], _, _>::new(edges.as_slice(), counts, displs);
println!("Sending...");
root_process
.scatter_varcount_into_root(&partition, &mut this_process_edges);
} else {
println!("Receiving...");
root_process.scatter_varcount_into(&mut this_process_edges);
};
println!("[{rank}] WTF? {this_process_edges:?}");
// Each process analyzes the non-local edges that are contained in its portion
// of the graph.
// Each process determines which processors stores the non-local vertices
// corresponding to the non-local edges.
// All the processes are communicating to figure out which process needs to
// send what data to the other processes.
// The processes perform the transfers of non-local labels and updates of
// local labels until convergence.
// The results are gathered to a single process, which writes them to the
// disk.
Ok(())
}
#[derive(Debug, Equivalence)]
struct Edge {
from_node: usize,
to_node: usize,
}