From 68a1e749dc30fdb3f143d777d18b8b31e793a235 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Sun, 10 Dec 2023 15:40:31 -0600 Subject: [PATCH] cuda shit --- .envrc | 1 + .gitignore | 3 +- assignments/04/.gitignore | 2 + assignments/04/ASSIGNMENT.md | 235 +++ assignments/04/Makefile | 7 + assignments/04/dataset/small_gaussian.txt | 2049 +++++++++++++++++++++ assignments/04/km_cuda.cu | 105 ++ assignments/04/plot.sh | 10 + assignments/04/plot_clusters2D.m | 23 + flake.lock | 74 + flake.nix | 19 + 11 files changed, 2527 insertions(+), 1 deletion(-) create mode 100644 .envrc create mode 100644 assignments/04/.gitignore create mode 100644 assignments/04/ASSIGNMENT.md create mode 100644 assignments/04/Makefile create mode 100755 assignments/04/dataset/small_gaussian.txt create mode 100644 assignments/04/km_cuda.cu create mode 100755 assignments/04/plot.sh create mode 100644 assignments/04/plot_clusters2D.m create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index bd6db2a..0c4b077 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store -/target \ No newline at end of file +/target +.direnv diff --git a/assignments/04/.gitignore b/assignments/04/.gitignore new file mode 100644 index 0000000..76d889c --- /dev/null +++ b/assignments/04/.gitignore @@ -0,0 +1,2 @@ +dataset/large_cpd.txt +km_cuda diff --git a/assignments/04/ASSIGNMENT.md b/assignments/04/ASSIGNMENT.md new file mode 100644 index 0000000..bdc8825 --- /dev/null +++ b/assignments/04/ASSIGNMENT.md @@ -0,0 +1,235 @@ +Introduction + +The purpose of this assignment is for you to become familiar with GPU programming and the CUDA API by parallelizing a common algorithm in data mining: k-means clustering. + +You need to write a program called km_cuda that will accept the following parameters as input: a filename of data points, the number of clusters, the number of thread blocks, and the number of threads per block. Your program should read in the specified file, cluster the given data points, and output the cluster assignments. + + +K-Means Clustering Algorithm + +The k-means clustering algorithm clusters N data points into K clusters. Each cluster is characterized by a centroid, which is a point representing the average of all data points within the cluster. The algorithm proceeds as follows: + +1. Select the initial K centroids. + a. For reproducibility, use points 0, 1, ..., K-1. +2. Assign each data point to the closest centroid (measured via Euclidean distance). +3. While not converged: + a. Update each centroid to be the average coordinate of all contained data points. + b. Assign all data points to the closest centroid (measured via Euclidean distance). + +Convergence is detected when no data points change their cluster assignment, or if the maximum number of iterations have been executed. For this assignment, you should set the maximum number of iterations to twenty. Additional material on the k-means algorithm can be found in K-Means.pdf + +Download K-Means.pdf. + + +Input/Output Formats + +Each program will take as input one file (the list of data points), and output two files ("clusters.txt": the cluster assignments and "centroids.txt": the centers of each cluster). + +The input file contains N+1 lines. The first line contains two space-separated integers: the number of data points (N), and the dimensionality of each data point (D). The following N lines each contain D space-separated floating-point numbers which represent the coordinates of the current data point. Each floating-point number contains at least one digit after the decimal point. For example, an input with four two-dimensional data points would be stored in a file as: + + + +4 2 +502.1 505.9 +504.0 489.4 +515.2 514.7 +496.7 498.3 + + + +The output file cluster assignments must be called clusters.txt and contain N lines. Each line should contain a single zero-indexed integer which specifies the cluster that the current data point belongs to. For example, a clustering of the above input file into two clusters may look like: + + + +0 +0 +1 +0 + + + +The second output file, centroids.txt, should follow the same format as the input data file. It should contain K data points, one for each cluster. Each coordinate should be written with at least three digits after the decimal point. + + + +Your program must also print the clustering time to standard out. You should use a high-precision, monotonic, wall-clock timer and also omit the time spent reading and writing to files. We recommend the function clock_gettime() when on a Linux system. Here is a function that you may use for timing: + + + +```c +/* Gives us high-resolution timers. */ +#define _POSIX_C_SOURCE 199309L +#include + +/* OSX timer includes */ +#ifdef __MACH__ + #include + #include +#endif + +/** +* @brief Return the number of seconds since an unspecified time (e.g., Unix +* epoch). This is accomplished with a high-resolution monotonic timer, +* suitable for performance timing. +* +* @return The number of seconds. +*/ +static inline double monotonic_seconds() { +#ifdef __MACH__ + /* OSX */ + static mach_timebase_info_data_t info; + static double seconds_per_unit; + if(seconds_per_unit == 0) { + mach_timebase_info(&info); + seconds_per_unit = (info.numer / info.denom) / 1e9; + } + return seconds_per_unit * mach_absolute_time(); +#else + /* Linux systems */ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec + ts.tv_nsec * 1e-9; +#endif +} +``` + + + +You should use the following function to output your clustering time: + +```c +/** +* @brief Output the seconds elapsed while clustering. +* +* @param seconds Seconds spent on k-means clustering, excluding IO. +*/ +static void print_time(double const seconds) +{ + printf("k-means clustering time: %0.04fs\n", seconds); +} +``` + + + +Timing information should be the ONLY thing printed to standard out. + + + +Failure to follow any of these output instructions will result in significant loss of points. +Testing + +Test inputs can be found in /export/scratch/csci5451_f23/hw4_data on any of the cuda lab machines. We provide two test files: small_gaussian.txt and large_cpd.txt. The former is a small two-dimensional dataset that you should use for testing the correctness of your code. + +The cuda machines are located at csel-cuda-0{1..5}.cselabs.umn.edu. You must first load the cuda modules with the following commands before using nvcc. + +module load soft/cuda/local +module initadd soft/cuda/local + +If the command 'module' cannot be found. Add the following lines into your ~/.bashrc file. + +```bash +MODULESINIT="/usr/local/modules-tcl/init/bash" + +if [ -f $MODULESINIT ]; then + + . $MODULESINIT + + module load java system soft/ocaml soft/cuda/local + +fi + +unset MODULESINIT +``` + +After adding, run + +``` +source ~/.bashrc +``` + +More info on testing/using the cuda machines can be found at Parallel Lab Systems. + +You should only run your code on one of the cuda machines. You will use the last digit of your student ID to select the machine. ID's ending in {0, 5} should use cuda01, ID's ending in {1, 6} should use cuda02, ID's ending in {3, 7} should use cuda03, ID's ending in {4, 8} should use cuda04, and ID's ending in {5, 9} should use cuda05. + +We provide a short script for plotting clustered 2D data (such as small_gaussian.txt). Download and extract plot_clusters.tar.gz + +Download plot_clusters.tar.gz. We provide plotting scripts and small_gaussian.txt inside the package. The plotting scripts rely on Octave, an open source alternative to Matlab. The Octave package can be loaded via 'module load math/octave'. Cluster the data with two clusters, place your files centroids.txt and clusters.txt inside of the plot/ directory, and run: + + + +$ ./plot.sh data/small_gaussian.txt + + +If your clustering is correct, you should see a plot similar to the one below. Data points inside the same cluster are colored the same. Centroids are marked clearly in the center of each cluster. + +clusters.png + +For the longer running tests, you should look into CUDA compiler optimization flags as well as the screen + +Links to an external site. command as these will be helpful. + +Remember that the TA will be evaluating your data with a different data sets than those provided for testing. +What you need to turn in +Download What you need to turn in + + The source code of your programs. + A short report including the following parts: + A short description of how you went about parallelizing the k-means algorithm. You should include how you decomposed the problem and why, i.e., what were the tasks being parallelized. + Give details about how many elements and how the computations in your kernels are handled by a thread. + Ensure you include details about the thread hierarchy, i.e., whether the threads are organized in a 1D, 2D, or, 3D fashion in a thread-block, and whether the thread-blocks are arranged 1D, 2D, or, 3D grid. NOTE: If you choose to write CUDA kernels where the number of thread blocks is determined dynamically by the program during runtime, then send -1 as the input argument for the number of thread blocks to the invocation. In your program, use -1 as a flag to indicate that the number of thread blocks will need to be computed during runtime. + You need to perform a parameter study in order to determine how the number of elements processed by a thread and the size of a thread-block, i.e., the #threads in a block, affect the performance of your algorithm. Your writeup should contain some results showing the runtime that you obtained for different choices. + You should include results on the 'large_cpd.txt' dataset with 256, 512, and 1024 clusters. + Remember, speed counts. Programs that fail to use the GPU efficiently will lose significant points. + +Do NOT include the test files; TAs will have their own test files for grading. You will lose significant points for including test files. + + + +Additional specifications related to assignment submission + + A makefile must be provided to compile and generate the executable. The executable should be named: + km_cuda + Program invocation: Your programs should take as an argument the input file to be read from, the number of clusters, the number of thread blocks, and the number of threads per block to be used for parallel execution. + For example, with 64 thread blocks and 128 threads, your program would be invoked as follows: + +./km_cuda /export/scratch/CSCI-5451/assignment-1/large_cpd.txt 512 64 128 + + NOTE: If you choose to write CUDA kernels where the number of thread blocks is determined dynamically by the program during runtime, then send -1 as the input argument for the number of thread blocks during invocation. Example: + +km_cuda /export/scratch/CSCI-5451/assignment-1/large_cpd.txt 512 -1 128 + + All files (code + report) MUST be in a single directory and the directory's name MUST be your UMN login ID (e.g., your UMN email or Moodle username). Your submission directory MUST include at least the following files (other auxiliary files may also be included): + +/km_cuda.c +/Makefile +/report.pdf + +If you choose to code in C++, then replace the .c suffixes with .cpp or .cc. + + Submission MUST be in .tar.gz + + The following sequence of commands should work on your submission file: + +tar xzvf .tar.gz +cd +make +ls -ld km_cuda + +This ensures that your submission is packaged correctly, your directory is named correctly, your makefile works correctly, and your output executables are named correctly. If any of these does not work, modify it so that you do not lose points. The TAs can answer questions about correctly formatting your submission BEFORE the assignment is due. Do not expect them to answer questions the night it is due. + + + +Failure to follow any of these submission instructions will result in significant loss of points. + + + + +Evaluation criteria + +The goal for this assignment is for you to become familiar with the APIs and not so much for developing the most efficient parallel program (this will be done later). As such, full points will be given to the programs that: + + follows the assignment directions; + solve the problem correctly; + do so in parallel (i.e., both clustering sub-steps are parallelized); + +The speedups obtained will probably depend on the size of the input file. It is not expected that you to get good speedups for small files, but you should be able to get speedups for large files. diff --git a/assignments/04/Makefile b/assignments/04/Makefile new file mode 100644 index 0000000..26f210d --- /dev/null +++ b/assignments/04/Makefile @@ -0,0 +1,7 @@ +.PHONY: clean + +km_cuda: km_cuda.cu + nvcc -g -o $@ $< + +clean: + rm -f km_cuda diff --git a/assignments/04/dataset/small_gaussian.txt b/assignments/04/dataset/small_gaussian.txt new file mode 100755 index 0000000..b38a654 --- /dev/null +++ b/assignments/04/dataset/small_gaussian.txt @@ -0,0 +1,2049 @@ +2048 2 +509 502 +600 599 +516 507 +607 599 +589 596 +593 607 +499 499 +504 517 +513 517 +510 495 +600 600 +608 600 +603 586 +601 607 +590 598 +486 496 +605 606 +503 495 +599 594 +586 594 +496 508 +586 615 +497 481 +487 491 +502 481 +497 501 +512 506 +602 603 +523 506 +492 509 +594 603 +611 611 +500 485 +598 592 +488 485 +590 602 +503 488 +602 612 +496 523 +589 591 +508 503 +488 502 +585 597 +507 507 +584 594 +594 606 +592 608 +585 597 +497 497 +510 488 +590 607 +608 614 +594 601 +512 487 +489 503 +605 592 +504 489 +600 597 +599 591 +605 598 +496 502 +609 609 +608 595 +506 498 +610 589 +490 494 +499 490 +519 491 +501 506 +596 622 +603 597 +609 581 +589 601 +602 584 +588 608 +600 596 +601 609 +494 483 +501 499 +577 599 +593 588 +601 592 +496 509 +503 500 +495 507 +505 511 +489 499 +484 512 +613 597 +483 498 +587 611 +501 494 +493 488 +600 591 +602 593 +605 568 +582 604 +497 495 +606 605 +493 494 +583 598 +520 499 +613 615 +492 501 +602 600 +596 599 +578 601 +612 615 +502 493 +505 502 +485 512 +596 602 +605 611 +509 491 +590 614 +492 498 +481 510 +504 503 +605 588 +514 505 +500 511 +609 612 +517 494 +591 612 +614 609 +504 495 +509 482 +499 494 +608 607 +592 603 +591 599 +504 520 +600 599 +502 496 +485 513 +503 491 +506 504 +593 610 +506 491 +493 518 +611 610 +511 491 +609 599 +517 505 +602 611 +605 601 +595 614 +578 608 +595 593 +480 483 +603 603 +494 514 +515 509 +609 584 +492 481 +503 508 +606 596 +600 589 +500 512 +520 495 +576 599 +572 593 +517 501 +613 578 +503 492 +494 501 +584 603 +604 589 +610 599 +498 507 +610 602 +595 607 +617 603 +504 500 +612 596 +612 597 +492 495 +595 609 +596 609 +503 497 +605 613 +484 484 +497 474 +482 500 +600 605 +605 579 +606 609 +582 598 +478 499 +498 495 +497 491 +484 507 +492 492 +492 501 +512 488 +492 509 +593 582 +617 606 +597 613 +502 498 +502 488 +494 493 +590 598 +588 602 +496 497 +608 616 +509 504 +502 512 +504 489 +586 604 +632 603 +587 594 +608 603 +601 601 +507 502 +508 493 +503 499 +498 490 +500 512 +602 597 +607 613 +492 504 +596 599 +484 495 +510 484 +473 512 +608 599 +500 495 +602 595 +508 473 +517 498 +611 602 +509 518 +590 590 +497 484 +503 496 +593 605 +485 491 +494 488 +488 514 +589 598 +595 591 +499 509 +492 477 +593 603 +504 510 +600 592 +513 509 +601 595 +502 509 +514 496 +499 496 +585 592 +600 603 +611 607 +481 509 +595 598 +512 495 +616 604 +492 499 +614 590 +605 581 +506 492 +599 590 +611 612 +514 497 +628 607 +492 509 +497 500 +488 505 +504 492 +504 488 +586 577 +603 600 +503 516 +503 485 +622 588 +606 585 +520 499 +509 506 +484 479 +501 499 +595 597 +500 513 +610 596 +501 488 +606 597 +519 488 +501 489 +500 508 +491 483 +591 600 +593 593 +622 585 +501 485 +596 603 +588 599 +585 601 +594 586 +601 594 +506 509 +596 616 +496 488 +506 492 +618 610 +599 583 +605 585 +491 499 +497 523 +498 475 +602 590 +508 492 +604 584 +476 508 +502 485 +511 500 +501 486 +500 503 +498 504 +585 610 +490 499 +513 499 +505 516 +486 507 +593 577 +598 603 +602 618 +487 483 +611 607 +504 516 +487 494 +590 596 +595 607 +502 499 +585 606 +594 597 +508 496 +611 584 +603 576 +591 594 +503 496 +604 589 +603 591 +609 609 +497 490 +486 509 +498 498 +610 587 +613 617 +506 499 +601 607 +616 610 +483 495 +478 509 +493 499 +588 587 +599 601 +602 601 +605 602 +615 616 +597 626 +604 580 +468 506 +517 498 +604 600 +597 604 +516 509 +482 497 +488 495 +594 597 +589 604 +591 607 +596 608 +603 590 +493 499 +523 511 +510 524 +598 596 +609 599 +495 485 +486 505 +610 590 +497 509 +488 504 +493 492 +500 506 +594 596 +598 598 +603 602 +505 501 +499 512 +511 496 +497 486 +517 505 +499 493 +503 497 +518 495 +612 619 +488 499 +596 609 +590 603 +478 507 +588 595 +505 512 +598 591 +605 609 +606 614 +500 491 +497 491 +613 605 +597 605 +508 506 +503 487 +506 503 +606 602 +505 495 +500 501 +607 596 +596 576 +496 499 +611 603 +598 620 +592 616 +594 613 +587 601 +508 502 +592 597 +510 498 +611 597 +491 509 +599 609 +509 504 +496 511 +505 502 +512 498 +608 604 +497 494 +592 593 +613 594 +504 504 +603 611 +605 607 +502 496 +479 483 +512 492 +601 591 +482 498 +502 482 +490 489 +594 597 +509 482 +501 496 +584 604 +607 608 +500 508 +609 596 +606 615 +615 591 +590 594 +499 496 +531 507 +507 501 +499 502 +606 618 +614 600 +495 497 +597 603 +592 609 +518 497 +502 511 +589 592 +498 499 +603 609 +510 513 +503 499 +500 500 +495 499 +489 509 +516 489 +504 499 +593 582 +613 601 +492 500 +512 506 +512 498 +505 476 +579 600 +590 612 +585 620 +604 612 +618 599 +483 529 +507 519 +610 605 +493 487 +596 619 +506 507 +587 599 +503 491 +503 493 +492 507 +603 588 +613 612 +598 618 +495 503 +599 592 +597 596 +494 490 +500 503 +586 605 +489 504 +500 506 +606 610 +596 601 +586 598 +607 622 +609 584 +597 600 +506 499 +514 489 +604 602 +516 486 +498 494 +492 513 +504 492 +502 493 +606 595 +584 603 +503 508 +603 613 +514 514 +516 477 +592 604 +588 590 +490 493 +590 605 +492 489 +578 596 +508 512 +504 492 +618 602 +609 605 +504 492 +597 594 +500 502 +495 496 +507 487 +589 587 +488 494 +497 482 +621 593 +592 582 +503 508 +495 505 +595 605 +577 591 +488 501 +469 507 +499 487 +623 597 +603 614 +630 613 +593 598 +620 594 +605 594 +495 486 +607 620 +480 500 +614 597 +508 510 +573 610 +624 587 +590 606 +518 517 +574 607 +503 495 +598 592 +592 593 +493 522 +492 493 +493 494 +498 502 +608 589 +501 486 +607 591 +511 497 +502 512 +512 484 +610 618 +491 491 +502 475 +591 617 +497 481 +491 514 +611 601 +590 601 +494 501 +609 608 +605 615 +509 511 +488 511 +496 513 +598 602 +607 597 +488 488 +479 509 +495 491 +595 589 +592 588 +494 484 +510 502 +595 583 +600 599 +508 497 +600 596 +587 588 +494 495 +509 488 +589 601 +493 494 +604 594 +615 595 +500 517 +612 607 +481 509 +517 505 +605 595 +575 594 +496 514 +593 609 +587 607 +601 607 +491 489 +495 494 +500 491 +493 498 +505 497 +494 495 +593 608 +609 599 +616 608 +593 593 +579 595 +584 610 +498 489 +503 491 +503 493 +595 595 +594 587 +488 497 +612 590 +507 508 +525 502 +621 580 +588 600 +499 505 +583 607 +583 576 +592 591 +530 495 +589 600 +608 586 +602 602 +602 584 +606 604 +505 500 +502 498 +597 589 +503 493 +607 598 +604 611 +503 508 +500 506 +593 595 +594 607 +603 594 +500 498 +495 498 +509 498 +582 603 +501 499 +497 502 +493 518 +515 492 +604 606 +599 578 +600 603 +508 496 +500 492 +612 617 +598 603 +603 611 +501 514 +492 496 +586 615 +512 501 +603 599 +516 503 +598 613 +579 609 +493 520 +500 508 +598 592 +592 593 +584 596 +591 589 +598 595 +609 609 +510 486 +492 490 +596 604 +507 487 +577 596 +499 503 +500 493 +512 494 +592 602 +584 590 +616 606 +504 524 +602 597 +596 617 +507 499 +491 495 +594 627 +582 606 +494 492 +615 608 +617 617 +597 595 +593 614 +487 485 +591 590 +596 603 +589 604 +484 498 +495 503 +595 601 +619 584 +495 490 +597 578 +484 491 +593 591 +592 584 +491 521 +484 489 +602 603 +490 504 +611 601 +517 502 +510 503 +598 603 +501 493 +611 596 +610 608 +591 594 +605 591 +512 508 +489 488 +494 482 +502 515 +591 600 +619 624 +496 515 +595 588 +512 517 +594 584 +589 611 +500 497 +582 601 +603 606 +616 594 +602 610 +497 491 +491 491 +506 527 +508 508 +609 615 +502 510 +503 505 +604 600 +496 499 +510 515 +595 603 +505 494 +512 503 +599 593 +503 498 +500 522 +506 491 +489 506 +601 597 +480 477 +508 501 +514 488 +485 500 +581 595 +492 495 +502 507 +591 591 +505 494 +606 592 +497 507 +610 596 +502 503 +601 613 +509 500 +518 503 +509 502 +490 494 +510 490 +493 502 +502 481 +501 503 +610 611 +508 502 +485 484 +600 620 +486 512 +600 586 +494 489 +617 582 +496 495 +602 604 +597 614 +494 500 +583 603 +503 507 +600 598 +613 609 +612 610 +592 589 +501 507 +605 593 +488 510 +508 494 +490 499 +494 512 +494 491 +497 512 +495 490 +600 594 +581 599 +501 514 +593 606 +591 618 +497 502 +602 590 +592 601 +589 586 +507 490 +492 502 +612 580 +512 507 +610 600 +612 608 +496 497 +514 487 +595 599 +592 599 +496 503 +625 609 +514 514 +596 619 +511 491 +590 594 +520 497 +597 617 +602 600 +510 496 +496 492 +497 497 +601 604 +510 505 +592 593 +589 594 +509 468 +601 604 +502 501 +587 592 +498 496 +599 584 +606 607 +492 493 +613 605 +501 483 +503 504 +522 515 +593 594 +600 599 +491 489 +495 490 +600 610 +596 607 +504 509 +602 594 +516 471 +609 603 +516 509 +491 489 +506 483 +511 511 +502 511 +497 488 +601 591 +590 597 +488 502 +600 598 +505 511 +504 479 +599 616 +502 510 +489 465 +594 590 +577 606 +501 485 +584 593 +496 482 +594 588 +597 612 +507 509 +594 616 +584 601 +593 597 +496 477 +505 492 +602 606 +588 600 +597 589 +509 493 +507 493 +509 498 +492 479 +607 599 +489 499 +603 628 +609 597 +505 512 +495 507 +612 603 +600 600 +593 600 +615 582 +618 614 +595 598 +621 582 +500 494 +501 502 +494 502 +496 505 +605 607 +619 589 +617 585 +514 495 +593 596 +482 488 +589 609 +503 484 +598 612 +491 496 +580 606 +604 613 +604 604 +592 589 +612 601 +615 616 +509 484 +499 511 +488 496 +588 591 +607 609 +504 493 +504 501 +599 601 +502 492 +496 508 +499 494 +485 486 +602 599 +524 505 +493 504 +510 507 +610 588 +602 598 +617 614 +600 584 +511 489 +583 613 +594 590 +604 609 +597 591 +614 579 +590 600 +505 504 +512 505 +611 602 +593 613 +505 513 +493 488 +511 498 +490 500 +500 498 +583 592 +606 606 +599 595 +601 589 +511 508 +502 513 +600 600 +586 595 +511 501 +495 507 +507 506 +586 599 +497 499 +611 599 +497 485 +604 590 +584 597 +494 486 +594 607 +500 503 +597 619 +598 593 +590 596 +485 488 +615 594 +601 593 +608 609 +591 593 +599 620 +509 510 +595 594 +609 611 +503 493 +498 492 +604 607 +497 501 +506 507 +495 502 +611 601 +514 489 +609 603 +601 610 +606 595 +606 590 +596 600 +498 500 +603 591 +603 613 +595 607 +503 490 +499 516 +590 581 +610 599 +591 605 +492 500 +609 593 +591 607 +493 495 +494 506 +588 606 +596 586 +596 585 +505 513 +497 505 +619 604 +523 498 +601 605 +492 494 +597 608 +592 594 +599 598 +600 589 +502 479 +516 516 +610 617 +511 488 +492 518 +501 497 +489 500 +608 585 +510 491 +593 600 +486 503 +493 505 +620 606 +512 525 +514 500 +483 500 +478 494 +595 606 +491 504 +609 605 +511 498 +608 592 +500 514 +501 487 +590 605 +602 615 +590 604 +507 499 +507 483 +597 590 +502 504 +598 601 +590 602 +502 520 +594 600 +594 605 +509 468 +586 600 +599 609 +498 492 +598 620 +586 597 +594 598 +505 495 +504 515 +496 505 +502 484 +602 596 +491 503 +600 604 +600 600 +498 502 +507 486 +600 603 +505 494 +606 621 +497 492 +600 613 +582 578 +600 573 +510 494 +499 499 +528 509 +484 496 +614 598 +487 493 +606 602 +504 495 +487 519 +502 501 +498 500 +585 600 +502 505 +514 495 +489 511 +595 589 +612 586 +494 499 +486 506 +518 488 +489 506 +603 606 +604 587 +596 596 +587 610 +517 493 +608 602 +503 490 +594 596 +508 489 +489 518 +587 617 +515 527 +594 586 +603 594 +507 492 +515 527 +502 510 +599 607 +607 590 +502 505 +601 600 +589 615 +591 604 +506 495 +481 520 +480 496 +500 491 +600 606 +491 479 +601 614 +586 593 +590 615 +505 504 +494 511 +482 504 +479 495 +607 585 +611 604 +494 486 +618 598 +488 502 +502 480 +600 592 +604 591 +626 603 +500 494 +594 612 +505 502 +607 573 +605 607 +590 594 +509 494 +499 504 +507 492 +499 498 +605 600 +488 508 +597 612 +592 614 +612 609 +592 584 +612 604 +508 504 +498 500 +484 500 +595 600 +610 597 +590 605 +598 600 +599 592 +604 599 +521 500 +615 596 +511 500 +476 489 +592 602 +596 601 +596 616 +610 582 +597 615 +608 604 +580 601 +603 597 +501 500 +612 602 +493 492 +494 494 +609 585 +587 607 +593 599 +488 496 +589 601 +595 605 +493 504 +488 478 +494 497 +594 604 +600 591 +605 603 +485 508 +500 507 +597 615 +505 498 +504 517 +600 603 +582 605 +519 505 +593 596 +489 502 +599 602 +503 504 +504 507 +500 494 +606 603 +497 514 +501 503 +491 490 +494 496 +495 511 +576 606 +614 599 +502 490 +488 495 +496 499 +597 597 +612 599 +599 584 +604 605 +608 606 +608 594 +611 593 +603 592 +589 602 +483 488 +504 483 +502 497 +496 485 +620 598 +503 502 +604 586 +509 499 +601 586 +602 585 +460 495 +482 495 +581 603 +605 603 +598 598 +586 602 +496 491 +484 513 +591 610 +589 615 +500 508 +599 593 +605 580 +604 590 +503 507 +502 497 +498 507 +492 495 +590 599 +478 499 +588 608 +585 584 +599 606 +503 509 +597 596 +600 590 +603 581 +505 517 +599 593 +595 611 +512 500 +594 607 +500 508 +496 502 +584 607 +600 583 +597 591 +602 592 +494 503 +502 487 +519 518 +494 471 +597 598 +499 500 +499 506 +621 601 +613 608 +589 591 +593 589 +612 589 +601 597 +511 501 +592 587 +495 516 +589 602 +520 495 +506 489 +489 499 +580 588 +607 587 +627 609 +597 593 +491 496 +618 601 +583 601 +504 497 +500 491 +588 611 +507 517 +499 499 +503 493 +502 492 +482 513 +496 511 +589 597 +596 616 +485 503 +608 598 +501 499 +505 510 +509 498 +502 491 +607 602 +574 601 +495 509 +496 494 +490 491 +508 500 +608 589 +597 600 +508 498 +590 604 +507 516 +486 516 +613 601 +510 497 +602 604 +596 589 +504 515 +510 500 +499 513 +605 612 +483 519 +607 614 +503 491 +490 508 +614 586 +491 504 +506 498 +612 589 +497 483 +593 600 +599 596 +496 497 +504 498 +591 595 +512 514 +495 474 +607 589 +593 600 +599 600 +498 503 +478 490 +522 506 +590 591 +612 602 +505 504 +604 599 +615 604 +492 499 +490 511 +607 609 +499 502 +587 598 +588 598 +603 603 +493 504 +606 612 +595 598 +517 462 +503 496 +505 491 +615 602 +612 614 +594 602 +595 625 +598 606 +506 510 +500 518 +594 595 +607 584 +603 600 +602 576 +589 580 +594 598 +498 491 +604 612 +505 487 +485 506 +591 605 +496 490 +499 507 +607 606 +493 484 +490 509 +484 491 +506 503 +600 594 +595 619 +602 584 +594 598 +501 515 +502 499 +612 590 +509 519 +529 490 +499 505 +608 601 +597 605 +495 493 +620 612 +503 493 +596 583 +602 618 +477 490 +509 497 +626 599 +483 497 +592 582 +579 605 +504 496 +593 589 +618 591 +502 509 +494 494 +502 489 +587 585 +594 613 +499 506 +499 501 +484 511 +506 499 +485 489 +580 602 +491 497 +599 600 +498 478 +491 506 +497 504 +483 524 +600 590 +499 492 +610 612 +505 511 +590 592 +507 488 +486 488 +507 484 +615 597 +611 590 +494 516 +498 505 +605 588 +514 502 +479 481 +496 507 +516 506 +487 516 +497 504 +485 495 +601 603 +602 595 +589 610 +506 495 +591 596 +594 598 +493 496 +595 587 +503 508 +599 601 +589 591 +508 516 +598 592 +492 514 +598 593 +599 579 +603 595 +605 607 +512 506 +580 623 +495 507 +597 584 +513 507 +490 478 +492 502 +603 598 +613 599 +507 507 +597 614 +491 499 +602 598 +491 496 +489 505 +521 500 +608 594 +503 481 +599 600 +502 497 +505 510 +589 595 +608 585 +599 600 +593 622 +496 507 +503 494 +616 573 +498 505 +599 601 +484 484 +594 602 +507 478 +508 491 +482 512 +495 498 +493 507 +498 512 +513 501 +500 516 +487 488 +598 612 +596 597 +495 489 +504 487 +490 513 +487 486 +586 585 +496 513 +599 619 +498 486 +602 587 +609 599 +616 609 +599 587 +603 597 +486 494 +498 501 +583 608 +604 619 +608 595 +492 494 +611 604 +594 587 +520 507 +495 509 +497 491 +588 610 +506 487 +583 603 +616 590 +595 580 +584 605 +595 590 +608 594 +522 496 +512 508 +589 581 +513 492 +593 603 +611 606 +609 598 +615 615 +591 576 +594 593 +586 605 +503 493 +583 610 +504 498 +594 588 +621 600 +595 596 +507 486 +505 499 +600 606 +510 499 +509 504 +591 582 +495 507 +496 498 +601 606 +620 592 +485 502 +512 487 +615 590 +593 601 +509 514 +582 593 +497 487 +497 498 +488 519 +591 598 +605 611 +589 619 +594 621 +496 504 +603 589 +594 589 +595 592 +594 603 +503 505 +487 502 +496 506 +491 500 +596 593 +484 490 +496 502 +590 600 +489 491 +520 506 +505 505 +605 615 +505 503 +505 487 +606 593 +576 625 +574 608 +589 607 +579 594 +513 496 +588 588 +501 489 +493 504 +497 518 +596 578 +600 592 +577 603 +602 598 +498 511 +491 491 +594 601 +488 508 +575 573 +604 574 +512 498 +599 590 +597 598 +485 503 +499 490 +615 591 +604 591 +493 513 +509 514 +508 497 +489 503 +501 502 +493 471 +499 499 +497 506 +617 610 +504 489 +493 483 +489 494 +608 600 +496 508 +493 518 +592 588 +495 509 +593 592 +605 611 +491 503 +488 489 +503 508 +522 499 +488 518 +593 592 +592 620 +600 583 +599 613 +500 480 +610 580 +480 484 +615 613 +597 588 +493 517 +511 487 +600 608 +483 504 +601 599 +502 490 +605 594 +498 489 +603 612 +492 489 +616 611 +605 607 +611 604 +507 520 +508 490 +594 604 +592 594 +507 498 +590 612 +603 587 +580 607 +601 594 +473 503 +597 605 +497 506 +494 504 +472 501 +492 501 +484 496 +611 591 +607 595 +503 507 +593 596 +508 495 +485 476 +604 600 +512 499 +604 598 +614 594 +481 507 +597 609 +591 591 +597 586 +490 506 +601 616 +611 593 +594 607 +585 609 +610 578 +496 488 +506 508 +616 588 +598 598 +604 594 +482 495 +486 485 +608 617 +611 595 +606 591 +621 597 +503 505 +492 502 +596 596 +495 494 +586 616 +580 599 +515 505 +602 596 +509 492 +494 494 +585 580 +614 592 +592 581 +499 517 +474 494 +520 491 +503 497 +493 493 +490 490 +575 586 +505 498 +497 487 +487 516 +505 495 +504 481 +589 614 +500 495 +592 609 +588 617 +501 481 +599 602 +612 612 +481 487 +597 584 +482 497 +595 605 +495 499 +592 612 +601 587 +504 510 +605 591 +517 513 +618 614 +596 593 +596 580 +589 585 +593 610 +487 510 +602 611 +497 496 +501 508 +498 494 +487 496 +495 504 +476 485 +492 496 +504 507 +609 596 +488 480 +610 594 +499 504 +606 611 +495 510 +607 604 +618 584 +608 594 +504 506 +503 477 +510 510 +506 504 +582 611 +610 600 +598 586 +604 598 +484 505 +498 486 +612 606 +600 612 +603 617 +515 516 +495 497 +505 496 +509 495 +505 505 +592 601 +477 490 +609 596 +502 513 +485 487 +489 502 +594 609 +593 584 +612 604 +617 604 +513 503 +498 501 +589 579 +600 610 +503 483 +598 605 +499 500 +513 497 +505 508 +596 602 +505 496 +621 580 +589 591 +619 593 +592 606 +597 597 +515 482 +530 499 +589 605 +495 493 +605 596 +496 506 +488 499 +597 602 +589 587 +502 480 +593 586 +602 591 +503 505 +602 610 +497 487 +586 605 +627 594 +590 611 +516 501 +609 594 +599 613 +595 590 +494 507 +503 490 +609 586 +602 595 +506 496 +613 602 +592 593 +609 600 +529 505 +596 614 +587 595 +599 584 +508 502 +503 500 +601 603 +517 499 +500 485 +592 609 +511 491 +590 597 +502 496 +612 598 +620 604 +597 594 +515 514 +494 498 +500 496 +485 508 +492 487 +498 483 +493 495 +600 588 +498 496 +503 483 +600 606 +504 504 +578 606 +488 499 +494 521 +616 606 +506 499 +601 588 +611 606 +593 600 +587 604 +601 597 +496 494 +506 499 +519 503 +602 592 +498 484 +597 604 +603 606 +494 486 +587 608 +607 604 +602 607 +494 489 +490 490 +497 488 +613 620 +601 613 +510 486 +498 499 +508 498 +602 577 +504 503 +588 605 +502 490 +605 608 +613 621 +603 593 +500 500 +503 489 +598 579 +589 582 +529 516 +618 613 +510 480 +501 499 +501 509 +496 502 +520 502 +613 629 +612 597 +517 503 +500 501 +503 509 +611 608 +492 513 +616 619 +609 602 +588 609 +505 503 +605 596 +494 482 +494 509 +594 603 +587 598 +496 500 +600 594 +516 506 +497 491 +502 502 +507 509 +503 507 +498 495 +591 605 +502 488 +595 601 +520 496 +584 599 +585 606 +497 486 +596 606 +612 600 diff --git a/assignments/04/km_cuda.cu b/assignments/04/km_cuda.cu new file mode 100644 index 0000000..1b4d57a --- /dev/null +++ b/assignments/04/km_cuda.cu @@ -0,0 +1,105 @@ +// #define _POSIX_C_SOURCE 200809L +#include + +#define CUDACHECK(err) \ + do { \ + cuda_check((err), __FILE__, __LINE__); \ + } while (false) +inline void cuda_check(cudaError_t error_code, const char *file, int line) { + if (error_code != cudaSuccess) { + fprintf(stderr, "CUDA Error %d: %s. In file '%s' on line %d\n", error_code, + cudaGetErrorString(error_code), file, line); + fflush(stderr); + exit(error_code); + } +} + +__global__ void findDistanceToCentroid(float *centroidDistances, float *data) { + centroidDistances[blockIdx.x] = blockIdx.x; +} + +int main(int argc, char **argv) { + int runtimeVersion, driverVersion; + cudaRuntimeGetVersion(&runtimeVersion); + cudaDriverGetVersion(&driverVersion); + printf("Runtime Version: %d, Driver Version: %d\n", runtimeVersion, + driverVersion); + + char *data_file = argv[1]; + int num_clusters = atoi(argv[2]); + int num_thread_blocks = atoi(argv[3]); + int num_threads_per_block = atoi(argv[4]); + + int N, dim; + float *centroids, *data, *centroidDistances; + int *clusterMap; + +#pragma region Read in data + { + FILE *fp = fopen(data_file, "r"); + + // Read first line + size_t n; + char *line = NULL; + if (!getline(&line, &n, fp)) + return -1; + + sscanf(line, "%d %d", &N, &dim); + free(line); + line = NULL; + + // Allocate memory on the GPU + CUDACHECK( + cudaMalloc((void **)¢roids, num_clusters * dim * sizeof(float))); + cudaMalloc((void **)&clusterMap, N * sizeof(int)); + cudaMalloc((void **)&data, N * dim * sizeof(float)); + cudaMalloc((void **)¢roidDistances, N * num_clusters * sizeof(float)); + + // Read the rest of the lines + { + // Buffer for copying + int *currentLine = (int *)malloc(dim * sizeof(int)); + for (int i = 0; i < N; ++i) { + if (!getline(&line, &n, fp)) + return -1; + + for (int j = 0; j < dim; ++j) + sscanf(line, "%d", ¤tLine[j]); + + cudaMemcpy(&data[i * dim], currentLine, dim * sizeof(float), + cudaMemcpyHostToDevice); + } + free(currentLine); + } + + printf("Done copying.\n"); + + fclose(fp); + } +#pragma endregion + +#pragma region Select the initial K centroids + { + cudaMemcpy(centroids, data, num_clusters * dim * sizeof(float), + cudaMemcpyDeviceToDevice); + } +#pragma endregion + +#pragma region Assign each data point to the closest centroid, \ + measured via Euclidean distance. + { + findDistanceToCentroid<<<10, 10>>>(centroidDistances, data); + cudaDeviceSynchronize(); + printf("Shiet\n"); + + float wtf[10]; + cudaMemcpy(wtf, centroidDistances, 10 * sizeof(float), + cudaMemcpyDeviceToHost); + for (int i = 0; i < 10; ++i) { + printf("asdf %d %f\n", i, wtf[i]); + } + } +#pragma endregion + + return 0; +} diff --git a/assignments/04/plot.sh b/assignments/04/plot.sh new file mode 100755 index 0000000..98a1529 --- /dev/null +++ b/assignments/04/plot.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ "$#" -ne 1 ]; then + echo "usage: ./plot.sh "; + echo " NOTE: 'clusters.txt' must be in working directory."; + exit 1; +fi + +octave-cli --eval "plot_clusters2D('$1', 'clusters.txt', 'centroids.txt')" + diff --git a/assignments/04/plot_clusters2D.m b/assignments/04/plot_clusters2D.m new file mode 100644 index 0000000..180b531 --- /dev/null +++ b/assignments/04/plot_clusters2D.m @@ -0,0 +1,23 @@ + +function plot_clusters2D(points_file, clusters_file, centroids_file) + +X = load(points_file); +X(1,:) = []; % remove metadata + +clusters = load(clusters_file); + +centroids = load(centroids_file); +centroids(1,:) = []; % remove metadata + +f = figure(); +hold on + +nclusters = size(centroids,1); +for c=1:nclusters + points = X(clusters == c-1, :); + scatter(points(:,1), points(:,2)); + + scatter(centroids(c,1), centroids(c,2), '+k', 'LineWidth', 5, 'SizeData', 100); +end + +uiwait(f); diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..952b429 --- /dev/null +++ b/flake.lock @@ -0,0 +1,74 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "id": "flake-utils", + "type": "indirect" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1663551060, + "narHash": "sha256-e2SR4cVx9p7aW/XnVsGsWZBplApA9ZJUjc0fejJhnYo=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "8a5b9ee7b7a2b38267c9481f5c629c015108ab0d", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgsUnstable": { + "locked": { + "lastModified": 1702237358, + "narHash": "sha256-PagQSuIdXAueAaAujhtqecP2sjXSYDdYfp2UVwqbkP8=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "7eb0ff576d1bde14a3353ef85f8fba6fd57d32c7", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "nixpkgsUnstable": "nixpkgsUnstable" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..f96165d --- /dev/null +++ b/flake.nix @@ -0,0 +1,19 @@ +{ + inputs.nixpkgsUnstable.url = "github:nixos/nixpkgs"; + + outputs = { self, nixpkgs, nixpkgsUnstable, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + pkgsUnstable = import nixpkgsUnstable { + inherit system; + config.allowUnfreePredicate = pkg: + builtins.elem (nixpkgs.lib.getName pkg) [ "cudatoolkit" ]; + }; + in { + devShell = pkgs.mkShell { + packages = (with pkgs; [ clang-tools gdb octave ]) + ++ (with pkgsUnstable.cudaPackages_12; [ cudatoolkit ]); + }; + }); +}