├── .gitignore ├── Makefile ├── README ├── extsort.c ├── extsort.h ├── generate_data.sh ├── harness.sh ├── log ├── qsort.c ├── qsort.h └── util.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.dat 2 | *.log 3 | *.o 4 | extsort 5 | .*.swp 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DEBUG=#-g -ggdb -DDEBUG 2 | OPTS=-O2 3 | CFLAGS=${OPTS} ${DEBUG} -Wall -std=gnu99 4 | LIBS=-lpthread 5 | 6 | extsort: extsort.o qsort.o 7 | gcc -o extsort extsort.o qsort.o ${CFLAGS} ${LIBS} 8 | extsort.o: extsort.c extsort.h 9 | gcc -c -o extsort.o extsort.c ${CFLAGS} ${LIBS} 10 | qsort.o: qsort.c qsort.h 11 | gcc -c -o qsort.o qsort.c ${CFLAGS} ${LIBS} 12 | clean: 13 | rm -f *.o 14 | rm -f extsort 15 | rm bar*.dat 16 | rm foo*.dat 17 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umbrant/extsort/d72cac2ee09177d872780d4e6218d10b86a70b28/README -------------------------------------------------------------------------------- /extsort.c: -------------------------------------------------------------------------------- 1 | #include "extsort.h" 2 | 3 | // Number of pages in a run 4 | static unsigned long DATA_SIZE; 5 | static char* DATA_FILENAME; 6 | static unsigned long BUF_SIZE; 7 | static unsigned int IO_BUF_PAGES; 8 | 9 | int main(int argc, char* argv[]) 10 | { 11 | if(argc != 4) { 12 | printf("Invalid number of arguments (%d)\n", argc); 13 | usage(); 14 | } 15 | DATA_FILENAME = argv[1]; 16 | BUF_SIZE = atoi(argv[2])*(1<<20); // convert from MB to bytes 17 | IO_BUF_PAGES = atoi(argv[3]); 18 | 19 | int sort_fd = open(DATA_FILENAME, O_RDONLY); 20 | if(sort_fd < 0) { 21 | error("Could not open sort_fd!"); 22 | } 23 | 24 | // Get the data file's size 25 | struct stat s; 26 | int rv = fstat(sort_fd, &s); 27 | if(rv) { 28 | printf("%s\n", DATA_FILENAME); 29 | error("Could not fstat file!"); 30 | } 31 | DATA_SIZE = s.st_size; 32 | 33 | char* filename = (char*)calloc(1, 100); 34 | 35 | // initially, each run is just 1 page, so this is how many runs there are 36 | int run_length = 1; 37 | unsigned long num_runs = DATA_SIZE / PAGE_SIZE; 38 | if(DATA_SIZE % PAGE_SIZE) { 39 | num_runs++; 40 | } 41 | 42 | printf("Sorting %lu ints (%.02f MB)...\n", 43 | num_runs*INTS_SIZE, 44 | (double)num_runs*PAGE_SIZE / (1<<20)); 45 | 46 | char input_prefix[] = "foo_"; 47 | char output_prefix[] = "bar_"; 48 | 49 | long start_usecs = get_time_usecs(); 50 | 51 | while(num_runs > 1) { 52 | printf("Iterate: %lu runs left\n", num_runs); 53 | // Number of ways we can merge at once 54 | unsigned long num_ways = ((BUF_SIZE / PAGE_SIZE) / IO_BUF_PAGES) - 1; 55 | // Case for small sorts: fits in memory 56 | if(num_ways > num_runs) { 57 | num_ways = num_runs; 58 | } 59 | // Calculate how many multimerges need to be done to merge all runs 60 | unsigned long num_merges = num_runs / num_ways; 61 | if(num_runs % num_ways) { 62 | num_merges++; 63 | } 64 | 65 | unsigned long run_counter = 0; 66 | 67 | // Start iterating the multimerges 68 | for(int i=0; i= (num_runs/num_ways)*num_ways) { 74 | num_runs_in_merge = num_runs % num_ways; 75 | } 76 | 77 | // Allocate the runs and runfds we're using for this multimerge 78 | run_t** runs = (run_t**)calloc(num_runs_in_merge, sizeof(run_t*)); 79 | 80 | // Handle the first pass differently, since the numbers 81 | // are all coming out of the same file, we need to populate 82 | // the runs here instead of letting multimerge do it 83 | if(run_length == 1) { 84 | // Allocate different sized runs 85 | PRINTF("Base case: init and sorting pages\n"); 86 | for(int i=0; iitems = (int*)calloc(1, PAGE_SIZE); 89 | int bytes = read(sort_fd, runs[i]->items, PAGE_SIZE); 90 | runs[i]->length = bytes/sizeof(int); 91 | if(bytes == 0) { 92 | break; 93 | } 94 | } 95 | run_counter += num_runs_in_merge; 96 | 97 | PRINTF("Doing parallel qsort..."); 98 | parallel_qsort(runs, num_runs_in_merge); 99 | PRINTF("done!\n"); 100 | // Verify the quicksort 101 | #ifdef DEBUG 102 | PRINTF("Verifying qsort results..."); 103 | for(int i=0; ilength; j++) { 107 | if(!init) { 108 | temp = runs[i]->items[j]; 109 | init = 1; 110 | } 111 | 112 | if(runs[i]->items[j] < temp) { 113 | printf("Incorrect qsort! Run %d idx %d\n", 114 | i, j); 115 | exit(-1); 116 | } 117 | temp = runs[i]->items[j]; 118 | } 119 | } 120 | PRINTF("correct!\n"); 121 | #endif 122 | } 123 | else { 124 | for(int i=0; iitems); 149 | free(runs[i]); 150 | } 151 | } 152 | free(runs); 153 | 154 | } 155 | // Swap the input and output prefixes 156 | // This way the next merge uses the previous round's output 157 | // as input 158 | strcpy(filename, output_prefix); 159 | strcpy(output_prefix, input_prefix); 160 | strcpy(input_prefix, filename); 161 | 162 | // RUN_LENGTH increases by N_WAYS every iteration 163 | run_length *= num_ways; 164 | // Number of runs produced is one per merge, i.e. num_merges 165 | num_runs = num_merges; 166 | } 167 | 168 | long end_usecs = get_time_usecs(); 169 | double secs = (double)(end_usecs - start_usecs) / (double)1000000; 170 | printf("Done sorting.\n"); 171 | printf("Sorting took %.02f seconds.\n", secs); 172 | #ifdef DEBUG 173 | snprintf(filename, 100, "%s%d.dat", input_prefix, 0); 174 | verify(filename); 175 | #endif 176 | 177 | free(filename); 178 | 179 | return 0; 180 | } 181 | 182 | 183 | /* multimerge 184 | * 185 | * On the first pass, runs are passed already allocated. This is 186 | * indicated by the boolean parameter 187 | * 188 | * Further passes need to allocate IO_BUF_PAGES for each run and read 189 | * in based on the input_prefix and num_runs. We can't keep the fds 190 | * open because there might be too many, so reopen lazily. 191 | * 192 | * output_fd comes already open and initialized for writing. 193 | */ 194 | void multimerge(run_t** runs, char* input_prefix, int num_runs, int output_fd, int base) 195 | { 196 | // Allocate run bufs if not base case 197 | int run_offsets[num_runs]; 198 | char filename[20]; 199 | if(base == 0) { 200 | PRINTF("multimerge: allocating run bufs\n"); 201 | for(int i=0; iitems = (int*)calloc(1, IO_BUF_PAGES*PAGE_SIZE); 204 | snprintf(filename, 20, "%s%d.dat", input_prefix, i); 205 | int fd = open(filename, O_RDONLY); 206 | int bytes = read(fd, runs[i]->items, IO_BUF_PAGES*PAGE_SIZE); 207 | close(fd); 208 | 209 | runs[i]->length = bytes/sizeof(int); 210 | run_offsets[i] = bytes; 211 | } 212 | } 213 | 214 | int idx[num_runs]; 215 | int skip[num_runs]; 216 | 217 | int* output = (int*)malloc(IO_BUF_PAGES*PAGE_SIZE); 218 | int output_idx = 0; 219 | 220 | // This decrements every time a run is fully merged 221 | int live_runs = num_runs; 222 | 223 | for(int i=0; ilength > 0) { 228 | skip[i] = 0; 229 | } else { 230 | skip[i] = 1; 231 | live_runs--; 232 | } 233 | } 234 | 235 | // Merge runs together 236 | while(live_runs > 0) { 237 | // find min element across runs 238 | int init = 0; 239 | int min = -13; 240 | int min_run = -1; 241 | for(int j=0; jitems[idx[j]] < min) { 244 | min_run = j; 245 | min = runs[j]->items[idx[j]]; 246 | init = 1; 247 | } 248 | } 249 | } 250 | // put min into output buffer 251 | output[output_idx] = runs[min_run]->items[idx[min_run]]; 252 | idx[min_run]++; 253 | 254 | // Read in more of the run if the buf is done 255 | if(!skip[min_run] && idx[min_run] == runs[min_run]->length) { 256 | if(base) { 257 | skip[min_run] = 1; 258 | live_runs--; 259 | } else { 260 | // Reopen min_run's fd at right offset to get next chunk 261 | snprintf(filename, 20, "%s%d.dat", input_prefix, min_run); 262 | int fd = open(filename, O_RDONLY); 263 | lseek(fd, run_offsets[min_run], SEEK_SET); 264 | int bytes = read(fd, runs[min_run]->items, IO_BUF_PAGES*PAGE_SIZE); 265 | if(bytes > 0) { 266 | idx[min_run] = 0; 267 | runs[min_run]->length = bytes / sizeof(int); 268 | // skip the run in the future if the file is completely read 269 | } else { 270 | skip[min_run] = 1; 271 | live_runs--; 272 | } 273 | close(fd); 274 | run_offsets[min_run] += bytes; 275 | } 276 | } 277 | // Flush the write buffer to disk if necessary 278 | output_idx++; 279 | if(output_idx == IO_BUF_PAGES*INTS_SIZE) { 280 | // Verify the buf first 281 | int check = output[0]; 282 | for(int j=1; jitems); 306 | free(runs[i]); 307 | } 308 | } 309 | free(output); 310 | } 311 | 312 | 313 | void verify(char* filename) 314 | { 315 | printf("Verifying sort (%s)...\n", filename); 316 | int input_fd = open(filename, O_RDONLY); 317 | // Get the data file's size 318 | struct stat s; 319 | int rv = fstat(input_fd, &s); 320 | if(rv) { 321 | error("Could not fstat file!"); 322 | } 323 | int buf_size = IO_BUF_PAGES*PAGE_SIZE; 324 | int num_runs = s.st_size / (buf_size); 325 | if(s.st_size % buf_size) { 326 | num_runs++; 327 | } 328 | 329 | int* buf = (int*)calloc(1, buf_size); 330 | int current = 0; 331 | int init = 0; 332 | int error = 0; 333 | unsigned long count = 0; 334 | while(num_runs > 0) { 335 | int bytes = read(input_fd, buf, buf_size); 336 | for(int i=0; i \n"); 364 | printf("\tfilename: filename of file to be sorted\n"); 365 | printf("\tbuffer_size_mb: MBs of buffer to use for sorting\n"); 366 | printf("\tio_buf_pages: number of 4k pages to use for per-run IO buffering\n"); 367 | exit(1); 368 | } 369 | 370 | 371 | void error(const char* msg) 372 | { 373 | perror(msg); 374 | exit(-1); 375 | } 376 | 377 | long get_time_usecs() 378 | { 379 | struct timeval time; 380 | struct timezone tz; 381 | memset(&tz, '\0', sizeof(timezone)); 382 | gettimeofday(&time, &tz); 383 | long usecs = time.tv_sec*1000000 + time.tv_usec; 384 | 385 | return usecs; 386 | } 387 | -------------------------------------------------------------------------------- /extsort.h: -------------------------------------------------------------------------------- 1 | #ifndef EXTSORT_H 2 | #define EXTSORT_H 3 | 4 | #include "util.h" 5 | #include "qsort.h" 6 | 7 | int main(int argc, char* argv[]); 8 | void usage(); 9 | void error(const char* msg); 10 | void multimerge(run_t** runs, char* input_prefix, int num_runs, int output_fd, int base); 11 | void verify(char* filename); 12 | long get_time_usecs(); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /generate_data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | dd if=/dev/urandom of=random.dat bs=1M count=4 4 | -------------------------------------------------------------------------------- /harness.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for i in 128 256 384 512 4 | do 5 | for j in 512 1024 2048 4096 6 | do 7 | rm -f bar*.dat foo*.dat 8 | echo "Executing extsort $i $j" 9 | ./extsort random_1G.dat $i $j > ${i}_${j}.log 10 | done 11 | done 12 | -------------------------------------------------------------------------------- /log: -------------------------------------------------------------------------------- 1 | qsort_recurse right 576 1024 2 | qsort_recurse left 576 628 3 | qsort_recurse right 617 628 4 | qsort_recurse left 617 618 5 | qsort_recurse right 619 628 6 | qsort_recurse right 627 628 7 | qsort_recurse left 619 626 8 | qsort_recurse left 619 619 9 | qsort_recurse right 620 626 10 | qsort_recurse right 625 626 11 | qsort_recurse left 620 624 12 | qsort_recurse left 576 616 13 | qsort_recurse right 612 616 14 | qsort_recurse left 576 611 15 | qsort_recurse left 576 579 16 | qsort_recurse right 580 611 17 | qsort_recurse right 597 611 18 | qsort_recurse left 597 602 19 | qsort_recurse left 597 597 20 | qsort_recurse right 598 602 21 | qsort_recurse right 603 611 22 | qsort_recurse left 603 606 23 | qsort_recurse right 607 611 24 | qsort_recurse left 580 596 25 | qsort_recurse right 589 596 26 | qsort_recurse right 595 596 27 | qsort_recurse left 589 594 28 | qsort_recurse left 589 589 29 | qsort_recurse right 590 594 30 | qsort_recurse left 580 588 31 | qsort_recurse right 585 588 32 | qsort_recurse left 580 584 33 | qsort_recurse right 629 1024 34 | qsort_recurse right 951 1024 35 | qsort_recurse left 951 952 36 | qsort_recurse right 953 1024 37 | qsort_recurse right 993 1024 38 | qsort_recurse right 1009 1024 39 | qsort_recurse right 1021 1024 40 | qsort_recurse left 1009 1020 41 | qsort_recurse right 1019 1020 42 | qsort_recurse left 1009 1018 43 | qsort_recurse left 1009 1010 44 | qsort_recurse right 1011 1018 45 | qsort_recurse right 1017 1018 46 | qsort_recurse left 1011 1016 47 | qsort_recurse left 1011 1011 48 | qsort_recurse right 1012 1016 49 | qsort_recurse left 993 1008 50 | qsort_recurse left 993 993 51 | qsort_recurse right 994 1008 52 | qsort_recurse left 994 999 53 | qsort_recurse right 998 999 54 | qsort_recurse left 994 997 55 | qsort_recurse right 1000 1008 56 | qsort_recurse right 1006 1008 57 | qsort_recurse left 1000 1005 58 | qsort_recurse right 1004 1005 59 | qsort_recurse left 1000 1003 60 | qsort_recurse left 953 992 61 | qsort_recurse right 974 992 62 | qsort_recurse left 974 974 63 | qsort_recurse right 975 992 64 | qsort_recurse left 975 975 65 | qsort_recurse right 976 992 66 | qsort_recurse left 976 979 67 | qsort_recurse right 980 992 68 | qsort_recurse right 991 992 69 | qsort_recurse left 980 990 70 | qsort_recurse left 980 982 71 | qsort_recurse right 983 990 72 | qsort_recurse right 989 990 73 | qsort_recurse left 983 988 74 | qsort_recurse left 983 984 75 | qsort_recurse right 985 988 76 | qsort_recurse left 953 973 77 | qsort_recurse left 953 955 78 | qsort_recurse right 956 973 79 | qsort_recurse left 956 959 80 | qsort_recurse right 960 973 81 | qsort_recurse left 960 960 82 | qsort_recurse right 961 973 83 | qsort_recurse left 961 965 84 | qsort_recurse right 966 973 85 | qsort_recurse right 971 973 86 | qsort_recurse left 966 970 87 | qsort_recurse left 629 950 88 | qsort_recurse right 835 950 89 | qsort_recurse left 835 876 90 | qsort_recurse left 835 842 91 | qsort_recurse left 835 837 92 | qsort_recurse right 838 842 93 | qsort_recurse right 843 876 94 | qsort_recurse right 875 876 95 | qsort_recurse left 843 874 96 | qsort_recurse right 861 874 97 | qsort_recurse left 861 864 98 | qsort_recurse right 865 874 99 | qsort_recurse left 865 865 100 | qsort_recurse right 866 874 101 | qsort_recurse right 873 874 102 | qsort_recurse left 866 872 103 | qsort_recurse left 866 866 104 | qsort_recurse right 867 872 105 | qsort_recurse left 867 867 106 | qsort_recurse right 868 872 107 | qsort_recurse left 843 860 108 | qsort_recurse left 843 844 109 | qsort_recurse right 845 860 110 | qsort_recurse left 845 851 111 | qsort_recurse left 845 845 112 | qsort_recurse right 846 851 113 | qsort_recurse left 846 846 114 | qsort_recurse right 847 851 115 | qsort_recurse right 852 860 116 | qsort_recurse left 852 855 117 | qsort_recurse right 856 860 118 | qsort_recurse right 877 950 119 | qsort_recurse left 877 900 120 | qsort_recurse left 877 886 121 | qsort_recurse left 877 879 122 | qsort_recurse right 880 886 123 | qsort_recurse right 885 886 124 | qsort_recurse left 880 884 125 | qsort_recurse right 887 900 126 | qsort_recurse left 887 892 127 | qsort_recurse right 891 892 128 | qsort_recurse left 887 890 129 | qsort_recurse right 893 900 130 | qsort_recurse right 899 900 131 | qsort_recurse left 893 898 132 | qsort_recurse left 893 893 133 | qsort_recurse right 894 898 134 | qsort_recurse right 901 950 135 | qsort_recurse right 928 950 136 | qsort_recurse left 928 935 137 | qsort_recurse right 932 935 138 | qsort_recurse left 928 931 139 | qsort_recurse right 936 950 140 | qsort_recurse right 949 950 141 | qsort_recurse left 936 948 142 | qsort_recurse left 936 937 143 | qsort_recurse right 938 948 144 | qsort_recurse right 947 948 145 | qsort_recurse left 938 946 146 | qsort_recurse left 938 939 147 | qsort_recurse right 940 946 148 | qsort_recurse right 945 946 149 | qsort_recurse left 940 944 150 | qsort_recurse left 901 927 151 | qsort_recurse right 925 927 152 | qsort_recurse left 901 924 153 | qsort_recurse right 917 924 154 | qsort_recurse right 922 924 155 | qsort_recurse left 917 921 156 | qsort_recurse left 901 916 157 | qsort_recurse left 901 905 158 | qsort_recurse right 906 916 159 | qsort_recurse left 906 907 160 | qsort_recurse right 908 916 161 | qsort_recurse right 914 916 162 | qsort_recurse left 908 913 163 | qsort_recurse right 912 913 164 | qsort_recurse left 908 911 165 | qsort_recurse left 629 834 166 | qsort_recurse right 754 834 167 | qsort_recurse left 754 765 168 | qsort_recurse right 761 765 169 | qsort_recurse left 754 760 170 | qsort_recurse left 754 755 171 | qsort_recurse right 756 760 172 | qsort_recurse right 766 834 173 | qsort_recurse left 766 772 174 | qsort_recurse right 771 772 175 | qsort_recurse left 766 770 176 | qsort_recurse right 773 834 177 | qsort_recurse left 773 796 178 | qsort_recurse right 787 796 179 | qsort_recurse right 795 796 180 | qsort_recurse left 787 794 181 | qsort_recurse left 787 787 182 | qsort_recurse right 788 794 183 | qsort_recurse right 793 794 184 | qsort_recurse left 788 792 185 | qsort_recurse left 773 786 186 | qsort_recurse right 785 786 187 | qsort_recurse left 773 784 188 | qsort_recurse left 773 774 189 | qsort_recurse right 775 784 190 | qsort_recurse right 783 784 191 | qsort_recurse left 775 782 192 | qsort_recurse left 775 776 193 | qsort_recurse right 777 782 194 | qsort_recurse right 781 782 195 | qsort_recurse left 777 780 196 | qsort_recurse right 797 834 197 | qsort_recurse left 797 802 198 | qsort_recurse right 800 802 199 | qsort_recurse left 797 799 200 | qsort_recurse right 803 834 201 | qsort_recurse left 803 807 202 | qsort_recurse right 808 834 203 | qsort_recurse left 808 818 204 | qsort_recurse right 814 818 205 | qsort_recurse left 808 813 206 | qsort_recurse right 812 813 207 | qsort_recurse left 808 811 208 | qsort_recurse right 819 834 209 | qsort_recurse right 829 834 210 | qsort_recurse left 829 830 211 | qsort_recurse right 831 834 212 | qsort_recurse left 819 828 213 | qsort_recurse left 819 822 214 | qsort_recurse right 823 828 215 | qsort_recurse left 823 824 216 | qsort_recurse right 825 828 217 | qsort_recurse left 629 753 218 | qsort_recurse right 720 753 219 | qsort_recurse left 720 734 220 | qsort_recurse left 720 725 221 | qsort_recurse left 720 721 222 | qsort_recurse right 722 725 223 | qsort_recurse right 726 734 224 | qsort_recurse left 726 728 225 | qsort_recurse right 729 734 226 | qsort_recurse right 733 734 227 | qsort_recurse left 729 732 228 | qsort_recurse right 735 753 229 | qsort_recurse right 750 753 230 | qsort_recurse left 735 749 231 | qsort_recurse left 735 739 232 | qsort_recurse right 740 749 233 | qsort_recurse right 746 749 234 | qsort_recurse left 740 745 235 | qsort_recurse right 743 745 236 | qsort_recurse left 740 742 237 | qsort_recurse left 629 719 238 | qsort_recurse right 678 719 239 | qsort_recurse left 678 681 240 | qsort_recurse right 682 719 241 | qsort_recurse right 705 719 242 | qsort_recurse left 705 708 243 | qsort_recurse right 709 719 244 | qsort_recurse left 709 713 245 | qsort_recurse right 714 719 246 | qsort_recurse left 714 714 247 | qsort_recurse right 715 719 248 | qsort_recurse left 682 704 249 | qsort_recurse left 682 691 250 | qsort_recurse left 682 685 251 | qsort_recurse right 686 691 252 | qsort_recurse right 690 691 253 | qsort_recurse left 686 689 254 | qsort_recurse right 692 704 255 | qsort_recurse left 692 693 256 | qsort_recurse right 694 704 257 | qsort_recurse right 702 704 258 | qsort_recurse left 694 701 259 | qsort_recurse left 694 696 260 | qsort_recurse right 697 701 261 | qsort_recurse left 629 677 262 | qsort_recurse right 660 677 263 | qsort_recurse right 672 677 264 | qsort_recurse right 675 677 265 | qsort_recurse left 672 674 266 | qsort_recurse left 660 671 267 | qsort_recurse left 660 660 268 | qsort_recurse right 661 671 269 | qsort_recurse right 669 671 270 | qsort_recurse left 661 668 271 | qsort_recurse right 665 668 272 | qsort_recurse left 661 664 273 | qsort_recurse left 629 659 274 | qsort_recurse right 645 659 275 | qsort_recurse left 645 650 276 | qsort_recurse left 645 645 277 | qsort_recurse right 646 650 278 | qsort_recurse right 651 659 279 | qsort_recurse left 651 651 280 | qsort_recurse right 652 659 281 | qsort_recurse left 652 652 282 | qsort_recurse right 653 659 283 | qsort_recurse right 657 659 284 | qsort_recurse left 653 656 285 | qsort_recurse left 629 644 286 | qsort_recurse left 629 632 287 | qsort_recurse right 633 644 288 | qsort_recurse right 641 644 289 | qsort_recurse left 633 640 290 | qsort_recurse left 633 635 291 | qsort_recurse right 636 640 292 | qsort_recurse left 0 575 293 | qsort_recurse left 0 270 294 | qsort_recurse left 0 104 295 | qsort_recurse left 0 13 296 | qsort_recurse right 7 13 297 | qsort_recurse right 12 13 298 | qsort_recurse left 7 11 299 | qsort_recurse left 0 6 300 | qsort_recurse left 0 2 301 | qsort_recurse right 3 6 302 | qsort_recurse right 14 104 303 | qsort_recurse left 14 56 304 | qsort_recurse left 14 21 305 | qsort_recurse left 14 14 306 | qsort_recurse right 15 21 307 | qsort_recurse left 15 17 308 | qsort_recurse right 18 21 309 | qsort_recurse right 22 56 310 | qsort_recurse right 55 56 311 | qsort_recurse left 22 54 312 | qsort_recurse left 22 34 313 | qsort_recurse right 30 34 314 | qsort_recurse left 22 29 315 | qsort_recurse left 22 24 316 | qsort_recurse right 25 29 317 | qsort_recurse right 35 54 318 | qsort_recurse left 35 39 319 | qsort_recurse right 40 54 320 | qsort_recurse left 40 40 321 | qsort_recurse right 41 54 322 | qsort_recurse left 41 41 323 | qsort_recurse right 42 54 324 | qsort_recurse right 52 54 325 | qsort_recurse left 42 51 326 | qsort_recurse right 47 51 327 | qsort_recurse left 42 46 328 | qsort_recurse right 57 104 329 | qsort_recurse left 57 57 330 | qsort_recurse right 58 104 331 | qsort_recurse right 90 104 332 | qsort_recurse left 90 90 333 | qsort_recurse right 91 104 334 | qsort_recurse left 91 91 335 | qsort_recurse right 92 104 336 | qsort_recurse left 92 97 337 | qsort_recurse left 92 93 338 | qsort_recurse right 94 97 339 | qsort_recurse right 98 104 340 | qsort_recurse right 103 104 341 | qsort_recurse left 98 102 342 | qsort_recurse left 58 89 343 | qsort_recurse right 81 89 344 | qsort_recurse left 81 82 345 | qsort_recurse right 83 89 346 | qsort_recurse left 83 85 347 | qsort_recurse right 86 89 348 | qsort_recurse left 58 80 349 | qsort_recurse right 70 80 350 | qsort_recurse left 70 73 351 | qsort_recurse right 74 80 352 | qsort_recurse right 79 80 353 | qsort_recurse left 74 78 354 | qsort_recurse left 58 69 355 | qsort_recurse right 65 69 356 | qsort_recurse left 58 64 357 | qsort_recurse right 62 64 358 | qsort_recurse left 58 61 359 | qsort_recurse right 105 270 360 | qsort_recurse right 248 270 361 | qsort_recurse right 269 270 362 | qsort_recurse left 248 268 363 | qsort_recurse left 248 253 364 | qsort_recurse left 248 248 365 | qsort_recurse right 249 253 366 | qsort_recurse right 254 268 367 | qsort_recurse right 262 268 368 | qsort_recurse right 266 268 369 | qsort_recurse left 262 265 370 | qsort_recurse left 254 261 371 | qsort_recurse left 254 254 372 | qsort_recurse right 255 261 373 | qsort_recurse left 255 256 374 | qsort_recurse right 257 261 375 | qsort_recurse left 105 247 376 | qsort_recurse left 105 135 377 | qsort_recurse left 105 108 378 | qsort_recurse right 109 135 379 | qsort_recurse right 123 135 380 | qsort_recurse left 123 126 381 | qsort_recurse right 127 135 382 | qsort_recurse left 127 127 383 | qsort_recurse right 128 135 384 | qsort_recurse left 128 128 385 | qsort_recurse right 129 135 386 | qsort_recurse right 133 135 387 | qsort_recurse left 129 132 388 | qsort_recurse left 109 122 389 | qsort_recurse left 109 112 390 | qsort_recurse right 113 122 391 | qsort_recurse left 113 116 392 | qsort_recurse right 117 122 393 | qsort_recurse right 121 122 394 | qsort_recurse left 117 120 395 | qsort_recurse right 136 247 396 | qsort_recurse left 136 151 397 | qsort_recurse right 147 151 398 | qsort_recurse left 136 146 399 | qsort_recurse right 142 146 400 | qsort_recurse left 136 141 401 | qsort_recurse right 139 141 402 | qsort_recurse left 136 138 403 | qsort_recurse right 152 247 404 | qsort_recurse right 202 247 405 | qsort_recurse right 244 247 406 | qsort_recurse left 202 243 407 | qsort_recurse left 202 221 408 | qsort_recurse right 216 221 409 | qsort_recurse right 219 221 410 | qsort_recurse left 216 218 411 | qsort_recurse left 202 215 412 | qsort_recurse left 202 205 413 | qsort_recurse right 206 215 414 | qsort_recurse right 212 215 415 | qsort_recurse left 206 211 416 | qsort_recurse right 209 211 417 | qsort_recurse left 206 208 418 | qsort_recurse right 222 243 419 | qsort_recurse right 239 243 420 | qsort_recurse left 222 238 421 | qsort_recurse left 222 228 422 | qsort_recurse right 226 228 423 | qsort_recurse left 222 225 424 | qsort_recurse right 229 238 425 | qsort_recurse left 229 232 426 | qsort_recurse right 233 238 427 | qsort_recurse left 233 233 428 | qsort_recurse right 234 238 429 | qsort_recurse left 152 201 430 | qsort_recurse left 152 160 431 | qsort_recurse left 152 154 432 | qsort_recurse right 155 160 433 | qsort_recurse right 158 160 434 | qsort_recurse left 155 157 435 | qsort_recurse right 161 201 436 | qsort_recurse right 197 201 437 | qsort_recurse left 161 196 438 | qsort_recurse right 180 196 439 | qsort_recurse left 180 184 440 | qsort_recurse right 185 196 441 | qsort_recurse left 185 185 442 | qsort_recurse right 186 196 443 | qsort_recurse left 186 187 444 | qsort_recurse right 188 196 445 | qsort_recurse left 188 190 446 | qsort_recurse right 191 196 447 | qsort_recurse right 195 196 448 | qsort_recurse left 191 194 449 | qsort_recurse left 161 179 450 | qsort_recurse left 161 166 451 | qsort_recurse right 165 166 452 | qsort_recurse left 161 164 453 | qsort_recurse right 167 179 454 | qsort_recurse left 167 172 455 | qsort_recurse left 167 167 456 | qsort_recurse right 168 172 457 | qsort_recurse right 173 179 458 | qsort_recurse left 173 174 459 | qsort_recurse right 175 179 460 | qsort_recurse right 271 575 461 | qsort_recurse right 453 575 462 | qsort_recurse right 521 575 463 | qsort_recurse right 573 575 464 | qsort_recurse left 521 572 465 | qsort_recurse left 521 528 466 | qsort_recurse right 527 528 467 | qsort_recurse left 521 526 468 | qsort_recurse left 521 521 469 | qsort_recurse right 522 526 470 | qsort_recurse right 529 572 471 | qsort_recurse left 529 532 472 | qsort_recurse right 533 572 473 | qsort_recurse left 533 538 474 | qsort_recurse left 533 533 475 | qsort_recurse right 534 538 476 | qsort_recurse right 539 572 477 | qsort_recurse left 539 549 478 | qsort_recurse right 548 549 479 | qsort_recurse left 539 547 480 | qsort_recurse left 539 539 481 | qsort_recurse right 540 547 482 | qsort_recurse left 540 540 483 | qsort_recurse right 541 547 484 | qsort_recurse right 546 547 485 | qsort_recurse left 541 545 486 | qsort_recurse right 550 572 487 | qsort_recurse right 571 572 488 | qsort_recurse left 550 570 489 | qsort_recurse right 561 570 490 | qsort_recurse right 566 570 491 | qsort_recurse left 561 565 492 | qsort_recurse left 550 560 493 | qsort_recurse left 550 554 494 | qsort_recurse right 555 560 495 | qsort_recurse right 559 560 496 | qsort_recurse left 555 558 497 | qsort_recurse left 453 520 498 | qsort_recurse right 513 520 499 | qsort_recurse right 517 520 500 | qsort_recurse left 513 516 501 | qsort_recurse left 453 512 502 | qsort_recurse right 487 512 503 | qsort_recurse right 511 512 504 | qsort_recurse left 487 510 505 | qsort_recurse left 487 488 506 | qsort_recurse right 489 510 507 | qsort_recurse right 509 510 508 | qsort_recurse left 489 508 509 | qsort_recurse left 489 490 510 | qsort_recurse right 491 508 511 | qsort_recurse right 507 508 512 | qsort_recurse left 491 506 513 | qsort_recurse left 491 491 514 | qsort_recurse right 492 506 515 | qsort_recurse right 505 506 516 | qsort_recurse left 492 504 517 | qsort_recurse left 492 492 518 | qsort_recurse right 493 504 519 | qsort_recurse left 493 493 520 | qsort_recurse right 494 504 521 | qsort_recurse right 503 504 522 | qsort_recurse left 494 502 523 | qsort_recurse left 494 494 524 | qsort_recurse right 495 502 525 | qsort_recurse left 495 495 526 | qsort_recurse right 496 502 527 | qsort_recurse right 501 502 528 | qsort_recurse left 496 500 529 | qsort_recurse left 453 486 530 | qsort_recurse right 479 486 531 | qsort_recurse right 484 486 532 | qsort_recurse left 479 483 533 | qsort_recurse left 453 478 534 | qsort_recurse right 468 478 535 | qsort_recurse left 468 469 536 | qsort_recurse right 470 478 537 | qsort_recurse right 477 478 538 | qsort_recurse left 470 476 539 | qsort_recurse left 470 470 540 | qsort_recurse right 471 476 541 | qsort_recurse left 471 471 542 | qsort_recurse right 472 476 543 | qsort_recurse left 453 467 544 | qsort_recurse left 453 457 545 | qsort_recurse right 458 467 546 | qsort_recurse left 458 458 547 | qsort_recurse right 459 467 548 | qsort_recurse left 459 460 549 | qsort_recurse right 461 467 550 | qsort_recurse right 466 467 551 | qsort_recurse left 461 465 552 | qsort_recurse left 271 452 553 | qsort_recurse right 423 452 554 | qsort_recurse left 423 424 555 | qsort_recurse right 425 452 556 | qsort_recurse left 425 429 557 | qsort_recurse right 430 452 558 | qsort_recurse left 430 432 559 | qsort_recurse right 433 452 560 | qsort_recurse left 433 438 561 | qsort_recurse right 437 438 562 | qsort_recurse left 433 436 563 | qsort_recurse right 439 452 564 | qsort_recurse left 439 444 565 | qsort_recurse left 439 440 566 | qsort_recurse right 441 444 567 | qsort_recurse right 445 452 568 | qsort_recurse left 445 447 569 | qsort_recurse right 448 452 570 | qsort_recurse left 271 422 571 | qsort_recurse left 271 301 572 | qsort_recurse left 271 279 573 | qsort_recurse left 271 271 574 | qsort_recurse right 272 279 575 | qsort_recurse left 272 272 576 | qsort_recurse right 273 279 577 | qsort_recurse right 278 279 578 | qsort_recurse left 273 277 579 | qsort_recurse right 280 301 580 | qsort_recurse right 294 301 581 | qsort_recurse right 298 301 582 | qsort_recurse left 294 297 583 | qsort_recurse left 280 293 584 | qsort_recurse left 280 282 585 | qsort_recurse right 283 293 586 | qsort_recurse right 292 293 587 | qsort_recurse left 283 291 588 | qsort_recurse left 283 286 589 | qsort_recurse right 287 291 590 | qsort_recurse right 302 422 591 | qsort_recurse left 302 338 592 | qsort_recurse left 302 306 593 | qsort_recurse right 307 338 594 | qsort_recurse right 331 338 595 | qsort_recurse left 331 331 596 | qsort_recurse right 332 338 597 | qsort_recurse left 332 334 598 | qsort_recurse right 335 338 599 | qsort_recurse left 307 330 600 | qsort_recurse left 307 312 601 | qsort_recurse left 307 308 602 | qsort_recurse right 309 312 603 | qsort_recurse right 313 330 604 | qsort_recurse right 323 330 605 | qsort_recurse left 323 325 606 | qsort_recurse right 326 330 607 | qsort_recurse left 313 322 608 | qsort_recurse right 321 322 609 | qsort_recurse left 313 320 610 | qsort_recurse left 313 313 611 | qsort_recurse right 314 320 612 | qsort_recurse right 319 320 613 | qsort_recurse left 314 318 614 | qsort_recurse right 339 422 615 | qsort_recurse left 339 340 616 | qsort_recurse right 341 422 617 | qsort_recurse right 387 422 618 | qsort_recurse right 416 422 619 | qsort_recurse right 421 422 620 | qsort_recurse left 416 420 621 | qsort_recurse left 387 415 622 | qsort_recurse left 387 389 623 | qsort_recurse right 390 415 624 | qsort_recurse left 390 396 625 | qsort_recurse left 390 390 626 | qsort_recurse right 391 396 627 | qsort_recurse left 391 391 628 | qsort_recurse right 392 396 629 | qsort_recurse right 397 415 630 | qsort_recurse left 397 405 631 | qsort_recurse left 397 397 632 | qsort_recurse right 398 405 633 | qsort_recurse left 398 398 634 | qsort_recurse right 399 405 635 | qsort_recurse left 399 401 636 | qsort_recurse right 402 405 637 | qsort_recurse right 406 415 638 | qsort_recurse right 414 415 639 | qsort_recurse left 406 413 640 | qsort_recurse right 411 413 641 | qsort_recurse left 406 410 642 | qsort_recurse left 341 386 643 | qsort_recurse left 341 361 644 | qsort_recurse left 341 341 645 | qsort_recurse right 342 361 646 | qsort_recurse left 342 342 647 | qsort_recurse right 343 361 648 | qsort_recurse left 343 349 649 | qsort_recurse left 343 344 650 | qsort_recurse right 345 349 651 | qsort_recurse right 350 361 652 | qsort_recurse right 357 361 653 | qsort_recurse left 350 356 654 | qsort_recurse right 354 356 655 | qsort_recurse left 350 353 656 | qsort_recurse right 362 386 657 | qsort_recurse left 362 372 658 | qsort_recurse right 370 372 659 | qsort_recurse left 362 369 660 | qsort_recurse right 366 369 661 | qsort_recurse left 362 365 662 | qsort_recurse right 373 386 663 | qsort_recurse right 382 386 664 | qsort_recurse left 373 381 665 | qsort_recurse left 373 375 666 | qsort_recurse right 376 381 667 | qsort_recurse right 380 381 668 | qsort_recurse left 376 379 669 | Incorrect sort 670 | -------------------------------------------------------------------------------- /qsort.c: -------------------------------------------------------------------------------- 1 | #include "qsort.h" 2 | 3 | static void qsort_recurse(run_t* data_ptr, int left, int right); 4 | static void swap(run_t* data_ptr, int first, int second); 5 | static int partition(run_t* data_ptr, int left, int right, int pivot_index); 6 | static void bubble(run_t* data_ptr, int left, int right); 7 | static void* qsort_worker(void *runs_per_thread); 8 | 9 | void ext_qsort(run_t* data_ptr) 10 | { 11 | qsort_recurse(data_ptr, 0, data_ptr->length-1); 12 | } 13 | 14 | 15 | void parallel_qsort(run_t** runs, int num_runs) 16 | { 17 | // Allocate work for each thread 18 | worker_data_t** runs_per_thread; 19 | runs_per_thread = (worker_data_t**)calloc(1, NUM_THREADS*sizeof(worker_data_t*)); 20 | int remainder = num_runs % NUM_THREADS; 21 | int offset = 0; 22 | for(int i=0; ioffset = offset; 26 | runs_per_thread[i]->length = num_runs / NUM_THREADS; 27 | runs_per_thread[i]->runs = runs; 28 | if(remainder) { 29 | runs_per_thread[i]->length++; 30 | remainder--; 31 | } 32 | offset += runs_per_thread[i]->length; 33 | } 34 | // Allocate each worker a subset of the runs to sort 35 | pthread_t workers[NUM_THREADS]; 36 | for(int i=0; ioffset; ioffset+data->length; i++) { 56 | ext_qsort(data->runs[i]); 57 | } 58 | return NULL; 59 | } 60 | 61 | 62 | 63 | static void qsort_recurse(run_t* data_ptr, int left, int right) 64 | { 65 | if(right > left) 66 | { 67 | if(right-left < 5) { 68 | return bubble(data_ptr, left, right); 69 | } 70 | int pivot_index = (right+left)/2; // median index as pivot 71 | int new_pivot_index = partition(data_ptr, left, right, pivot_index); 72 | if(new_pivot_index-1-left < right-new_pivot_index) { 73 | // left half 74 | qsort_recurse(data_ptr, left, new_pivot_index-1); 75 | // right half 76 | return qsort_recurse(data_ptr, new_pivot_index, right); 77 | } else { 78 | // right half 79 | qsort_recurse(data_ptr, new_pivot_index, right); 80 | // left half 81 | return qsort_recurse(data_ptr, left, new_pivot_index-1); 82 | } 83 | } 84 | } 85 | 86 | static int partition(run_t* data_ptr, int left, int right, int pivot_index) 87 | { 88 | int pivot_value = data_ptr->items[pivot_index]; 89 | 90 | // swap pivot with rightmost (swap it back later) 91 | swap(data_ptr, pivot_index, right); 92 | 93 | int store_index = left; 94 | 95 | int i; 96 | for(i=left; iitems[i] <= pivot_value) { 98 | swap(data_ptr, store_index, i); 99 | store_index++; 100 | } 101 | for(int i=0; ilength; i++) { 102 | } 103 | } 104 | swap(data_ptr, store_index, right); 105 | return store_index; 106 | } 107 | 108 | static void swap(run_t* data_ptr, int first, int second) 109 | { 110 | int temp = data_ptr->items[first]; 111 | data_ptr->items[first] = data_ptr->items[second]; 112 | data_ptr->items[second] = temp; 113 | } 114 | 115 | static void bubble(run_t* data_ptr, int left, int right) 116 | { 117 | int i,j; 118 | if(right == left) { 119 | return; 120 | } 121 | 122 | for(i=left; i<=right; i++) { 123 | for(j=left; j<=right-1-(i-left); j++) { 124 | if(data_ptr->items[j] > data_ptr->items[j+1]) { 125 | swap(data_ptr, j, j+1); 126 | } 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /qsort.h: -------------------------------------------------------------------------------- 1 | #ifndef QSORT_H 2 | #define QSORT_H 3 | 4 | #include "util.h" 5 | 6 | 7 | void ext_qsort(run_t* data_ptr); 8 | void parallel_qsort(run_t** runs, int num_runs); 9 | 10 | typedef struct worker_data { 11 | int offset; 12 | int length; 13 | run_t** runs; 14 | } worker_data_t; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | #ifdef DEBUG 18 | #define PRINTF(...) printf(__VA_ARGS__) 19 | #else 20 | #define PRINTF(...) 21 | #endif 22 | 23 | // Number of bytes in a page 24 | #define PAGE_SIZE (4*(1<<10)) 25 | #define INTS_SIZE PAGE_SIZE/sizeof(int) 26 | 27 | #define NUM_THREADS 8 28 | 29 | /* 30 | typedef struct { 31 | int items[PAGE_SIZE]; 32 | } page_t; 33 | */ 34 | 35 | typedef struct { 36 | int length; 37 | int* items; 38 | } run_t; 39 | 40 | void error(const char* msg); 41 | 42 | #endif 43 | --------------------------------------------------------------------------------