Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cmake.configureOnOpen": false
}
345 changes: 339 additions & 6 deletions README.md

Large diffs are not rendered by default.

Binary file added img/blocksize.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/compact_analysis.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/compact_scan.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/cpu_compact.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/down_sweep.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/scan_analysis.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/thrust.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/up_sweep.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
238 changes: 224 additions & 14 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,23 @@
*/

#include <cstdio>
#include <vector>
#include <numeric>
#include <stream_compaction/cpu.h>
#include <stream_compaction/naive.h>
#include <stream_compaction/efficient.h>
#include <stream_compaction/thrust.h>
#include "testing_helpers.hpp"

const int SIZE = 1 << 8; // feel free to change the size of array
const int SIZE = 1 << 20; // feel free to change the size of array
const int NPOT = SIZE - 3; // Non-Power-Of-Two
int *a = new int[SIZE];
int *b = new int[SIZE];
int *c = new int[SIZE];
int* a = new int[SIZE];
int* b = new int[SIZE];
int* c = new int[SIZE];

#define TEST 1 // 1: running test; 0: perform anaylsis

#if TEST
int main(int argc, char* argv[]) {
// Scan tests

Expand All @@ -30,6 +35,7 @@ int main(int argc, char* argv[]) {
genArray(SIZE - 1, a, 50); // Leave a 0 at the end to test that edge case
a[SIZE - 1] = 0;
printArray(SIZE, a, true);


// initialize b using StreamCompaction::CPU::scan you implement
// We use b for further comparison. Make sure your StreamCompaction::CPU::scan is correct.
Expand All @@ -51,41 +57,55 @@ int main(int argc, char* argv[]) {
printDesc("naive scan, power-of-two");
StreamCompaction::Naive::scan(SIZE, c, a);
printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)");
//printArray(SIZE, c, true);
printArray(SIZE, c, true);
printCmpResult(SIZE, b, c);

/* For bug-finding only: Array of 1s to help find bugs in stream compaction or scan
onesArray(SIZE, c);
// For bug-finding only: Array of 1s to help find bugs in stream compaction or scan
/*onesArray(SIZE, c);
printDesc("1s array for finding bugs");
StreamCompaction::Naive::scan(SIZE, c, a);
printArray(SIZE, c, true); */
printArray(SIZE, c, true);*/

zeroArray(SIZE, c);
printDesc("naive scan, non-power-of-two");
StreamCompaction::Naive::scan(NPOT, c, a);
printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)");
//printArray(SIZE, c, true);
printArray(SIZE, c, true);
printCmpResult(NPOT, b, c);

zeroArray(SIZE, c);
printDesc("work-efficient scan, power-of-two");
StreamCompaction::Efficient::scan(SIZE, c, a);
printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)");
//printArray(SIZE, c, true);
printArray(SIZE, c, true);
printCmpResult(SIZE, b, c);

zeroArray(SIZE, c);
printDesc("work-efficient scan, non-power-of-two");
StreamCompaction::Efficient::scan(NPOT, c, a);
printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)");
//printArray(NPOT, c, true);
printArray(NPOT, c, true);
printCmpResult(NPOT, b, c);

zeroArray(SIZE, c);
printDesc("work-efficient scan with shared memory, power-of-two");
StreamCompaction::Efficient::scanShared(SIZE, c, a);
printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)");
printArray(SIZE, c, true);
printCmpResult(SIZE, b, c);

zeroArray(SIZE, c);
printDesc("work-efficient scan with shared memory, non-power-of-two");
StreamCompaction::Efficient::scanShared(NPOT, c, a);
printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)");
printArray(NPOT, c, true);
printCmpResult(NPOT, b, c);

zeroArray(SIZE, c);
printDesc("thrust scan, power-of-two");
StreamCompaction::Thrust::scan(SIZE, c, a);
printElapsedTime(StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)");
//printArray(SIZE, c, true);
printArray(SIZE, c, true);
printCmpResult(SIZE, b, c);

zeroArray(SIZE, c);
Expand Down Expand Up @@ -137,18 +157,208 @@ int main(int argc, char* argv[]) {
printDesc("work-efficient compact, power-of-two");
count = StreamCompaction::Efficient::compact(SIZE, c, a);
printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)");
//printArray(count, c, true);
printArray(count, c, true);
printCmpLenResult(count, expectedCount, b, c);

zeroArray(SIZE, c);
printDesc("work-efficient compact, non-power-of-two");
count = StreamCompaction::Efficient::compact(NPOT, c, a);
printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)");
//printArray(count, c, true);
printArray(count, c, true);
printCmpLenResult(count, expectedNPOT, b, c);

system("pause"); // stop Win32 console from closing on exit
delete[] a;
delete[] b;
delete[] c;
}

#else
const int NUM_TESTS = 10;

double computeAverage(double* arr, int size) {
double sum = 0.0;
for (int i = 0; i < size; ++i) {
sum += arr[i];
}
return sum / size;
}

void testScan() {
// Scan tests

printf("\n");
printf("****************\n");
printf("** SCAN TESTS **\n");
printf("****************\n");

double* cpuScanTimes = new double[NUM_TESTS];
double* naiveScanTimes = new double[NUM_TESTS];
double* workEfficientScanTimes = new double[NUM_TESTS];
double* workEfficientScansharedTimes = new double[NUM_TESTS];
double* thrustScanTimes = new double[NUM_TESTS];

for (int i = 0; i < NUM_TESTS; ++i) {
genArray(SIZE - 1, a, 50); // Leave a 0 at the end to test that edge case
a[SIZE - 1] = 0;

zeroArray(SIZE, b);
// printDesc("cpu scan, power-of-two");
StreamCompaction::CPU::scan(SIZE, b, a);
cpuScanTimes[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation();

zeroArray(SIZE, c);
// printDesc("cpu scan, not power-of-two");
StreamCompaction::CPU::scan(NPOT, c, a);
evalCmpResult(NPOT, b, c);

zeroArray(SIZE, c);
StreamCompaction::Naive::scan(SIZE, c, a);
naiveScanTimes[i] = StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation();
evalCmpResult(SIZE, b, c);

zeroArray(SIZE, c);
// printDesc("naive scan, not power-of-two");
StreamCompaction::Naive::scan(NPOT, c, a);
evalCmpResult(NPOT, b, c);

zeroArray(SIZE, c);
// printDesc("work-efficient scan, power-of-two");
StreamCompaction::Efficient::scan(SIZE, c, a);
workEfficientScanTimes[i] = StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation();
evalCmpResult(SIZE, b, c);

zeroArray(SIZE, c);
// printDesc("work-efficient scan, not power-of-two");
StreamCompaction::Efficient::scan(NPOT, c, a);
evalCmpResult(NPOT, b, c);

zeroArray(SIZE, c);
// printDesc("work-efficient scan with shared memory, power-of-two");
StreamCompaction::Efficient::scanShared(SIZE, c, a);
workEfficientScansharedTimes[i] = StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation();
evalCmpResult(SIZE, b, c);

zeroArray(SIZE, c);
// printDesc("work-efficient scan with shared memory, not power-of-two");
StreamCompaction::Efficient::scanShared(NPOT, c, a);
evalCmpResult(NPOT, b, c);

zeroArray(SIZE, c);
// printDesc("thrust scan, power-of-two");
StreamCompaction::Thrust::scan(SIZE, c, a);
thrustScanTimes[i] = StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation();
evalCmpResult(SIZE, b, c);

zeroArray(SIZE, c);
// printDesc("thrust scan, not power-of-two");
StreamCompaction::Thrust::scan(NPOT, c, a);
evalCmpResult(NPOT, b, c);
}

printDesc("cpu scan, power-of-two");
printDoubleArray(NUM_TESTS, cpuScanTimes, true);
printf("%5f \n", computeAverage(cpuScanTimes, NUM_TESTS));

printDesc("naive scan,power-of-two");
printDoubleArray(NUM_TESTS, naiveScanTimes, true);
printf("%5f \n", computeAverage(naiveScanTimes, NUM_TESTS));

printDesc("work-efficient scan, power-of-two");
printDoubleArray(NUM_TESTS, workEfficientScanTimes, true);
printf("%5f \n", computeAverage(workEfficientScanTimes, NUM_TESTS));

printDesc("work-efficient scan with shared memory, power-of-two");
printDoubleArray(NUM_TESTS, workEfficientScansharedTimes, true);
printf("%5f \n", computeAverage(workEfficientScansharedTimes, NUM_TESTS));

printDesc("thrust scan, power-of-two");
printDoubleArray(NUM_TESTS, thrustScanTimes, true);
printf("%5f \n", computeAverage(thrustScanTimes, NUM_TESTS));


delete[] cpuScanTimes;
delete[] naiveScanTimes;
delete[] workEfficientScanTimes;
delete[] thrustScanTimes;
}

void testCompact() {
printf("\n");
printf("*****************************\n");
printf("** STREAM COMPACTION TESTS **\n");
printf("*****************************\n");

// Compaction tests

double* cpuCompact = new double[NUM_TESTS];
double* cpuCompactWithScan = new double[NUM_TESTS];
double* workEfficientCompact = new double[NUM_TESTS];

for (int i = 0; i < NUM_TESTS; ++i) {
genArray(SIZE - 1, a, 4); // Leave a 0 at the end to test that edge case
a[SIZE - 1] = 0;
//printArray(SIZE, a, true);

int count, expectedCount, expectedNPOT;

// initialize b using StreamCompaction::CPU::compactWithoutScan you implement
// We use b for further comparison. Make sure your StreamCompaction::CPU::compactWithoutScan is correct.
zeroArray(SIZE, b);
// printDesc("cpu compact without scan, power-of-two");
count = StreamCompaction::CPU::compactWithoutScan(SIZE, b, a);
cpuCompact[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation();
expectedCount = count;
evalCmpLenResult(count, expectedCount, b, b);

zeroArray(SIZE, c);
// printDesc("cpu compact without scan, non-power-of-two");
count = StreamCompaction::CPU::compactWithoutScan(NPOT, c, a);
expectedNPOT = count;
evalCmpLenResult(count, expectedNPOT, b, c);

zeroArray(SIZE, c);
// printDesc("cpu compact with scan");
count = StreamCompaction::CPU::compactWithScan(SIZE, c, a);
cpuCompactWithScan[i] = StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation();
evalCmpLenResult(count, expectedCount, b, c);

zeroArray(SIZE, c);
// printDesc("work-efficient compact, power-of-two");
count = StreamCompaction::Efficient::compact(SIZE, c, a);
workEfficientCompact[i] = StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation();
evalCmpLenResult(count, expectedCount, b, c);

zeroArray(SIZE, c);
// printDesc("work-efficient compact, non-power-of-two");
count = StreamCompaction::Efficient::compact(NPOT, c, a);
evalCmpLenResult(count, expectedNPOT, b, c);
}

printDesc("cpu compact without scan, power-of-two");
printDoubleArray(NUM_TESTS, cpuCompact, true);
printf("%5f \n", computeAverage(cpuCompact, NUM_TESTS));

printDesc("cpu compact with scan, power-of-two");
printDoubleArray(NUM_TESTS, cpuCompactWithScan, true);
printf("%5f \n", computeAverage(cpuCompactWithScan, NUM_TESTS));

printDesc("work-efficient compact, power-of-two");
printDoubleArray(NUM_TESTS, workEfficientCompact, true);
printf("%5f \n", computeAverage(workEfficientCompact, NUM_TESTS));

delete[] cpuCompact;
delete[] cpuCompactWithScan;
delete[] workEfficientCompact;
}

int main(int argc, char* argv[]) {
testScan();
// testCompact();

system("pause"); // stop Win32 console from closing on exit
delete[] a;
delete[] b;
delete[] c;
}
#endif
38 changes: 38 additions & 0 deletions src/testing_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ void printCmpResult(int n, T *a, T *b) {
cmpArrays(n, a, b) ? "FAIL VALUE" : "passed");
}

template<typename T>
void evalCmpResult(int n, T *a, T *b) {
if (cmpArrays(n, a, b)) {
printf(" % s \n", "FAIL VALUE");
}
}

template<typename T>
void printCmpLenResult(int n, int expN, T *a, T *b) {
if (n != expN) {
Expand All @@ -37,6 +44,25 @@ void printCmpLenResult(int n, int expN, T *a, T *b) {
cmpArrays(n, a, b) ? "FAIL VALUE" : "passed");
}

template<typename T>
void evalCmpLenResult(int n, int expN, T* a, T* b) {
if (n != expN) {
printf(" expected %d elements, got %d\n", expN, n);
}

if (n == -1 || n != expN) {
printf(" % s \n", "FAIL COUNT");
}
else {
if (cmpArrays(n, a, b)) {
printf(" % s \n", "FAIL VALUE");
}
}
/* printf(" %s \n",
(n == -1 || n != expN) ? "FAIL COUNT" :
cmpArrays(n, a, b) ? "FAIL VALUE" : "passed");*/
}

void zeroArray(int n, int *a) {
for (int i = 0; i < n; i++) {
a[i] = 0;
Expand Down Expand Up @@ -69,6 +95,18 @@ void printArray(int n, int *a, bool abridged = false) {
printf("]\n");
}

void printDoubleArray(int n, double* a, bool abridged = false) {
printf(" [ ");
for (int i = 0; i < n; i++) {
if (abridged && i + 2 == 15 && n > 16) {
i = n - 2;
printf("... ");
}
printf("%5f ", a[i]);
}
printf("]\n");
}

template<typename T>
void printElapsedTime(T time, std::string note = "")
{
Expand Down
Loading