Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
dd2b9ca
WIP: Add 2D heuristic implementation to cuFFTAdvisor
adammydla Jun 20, 2024
5ecfb60
Add new option to disallow 2D rotation
adammydla Sep 28, 2024
13d032a
Fix not using correct method definition syntax
adammydla Sep 28, 2024
c840a03
Fix not using correct arguments in optimizeXYZ call
Sep 28, 2024
416f060
Add exponent 11 to sizeOptimizer
adammydla Nov 19, 2024
9397707
Merge branch '2D-advisor' of https://github.com/adammydla/cuFFTAdviso…
adammydla Nov 19, 2024
654681c
Fix bugs in sizeOptimizer
adammydla Nov 20, 2024
376ae7f
Fix incorrect results in first benchmark test
Nov 20, 2024
31a6665
Recreate2D rotation heuristic
adammydla Nov 22, 2024
f2aa419
Add kernel count to size sorter
adammydla Nov 23, 2024
ef86e4d
Fix bugs in kernel count in Transform and GeneralTransform class
Nov 24, 2024
3619d7f
Add possibility to optimize only selected dimensions
adammydla Nov 27, 2024
3656850
Fix bugs in dimension optimization selection
Nov 27, 2024
3e2155d
Add check for invalid index access
adammydla Feb 19, 2025
ac1d681
Add initialization and comment to kernelInvocationX fields
adammydla Feb 19, 2025
0111f3e
Fix incorrect name in --countOfOptimizedDimensions option
adammydla Feb 19, 2025
ed94985
Merge remote-tracking branch 'origin/2D-advisor' into 2D-advisor
adammydla Feb 19, 2025
4540039
Fix wrongly comparing float with int
adammydla Feb 19, 2025
df8cf7b
Add constant MaxNumberOfOptimizedDimensions
adammydla Feb 19, 2025
f8c27fe
Fix error with dangling space in generalTransform.hpp
Mar 9, 2025
b906e45
Fix help message for --countOfOptimizedDimensions option
Mar 9, 2025
8a559f2
Merge branch '2D-advisor' of https://github.com/adammydla/cuFFTAdviso…
Mar 9, 2025
33bf700
Add MinimalCountOfUsedConfigurations constant
Mar 9, 2025
70bbf4b
Delete swapped2D field from GeneralTransform
Mar 9, 2025
fb8fd8a
Set fields originalX..Y..Z to be const
Mar 9, 2025
3059847
Add default initialization and constructors for struct Polynom
Mar 9, 2025
13391d3
Fix using 0 instead of actual values
Mar 9, 2025
eeff51a
Delete unused if branches in swapSizes2D
Mar 9, 2025
822ce3a
Add documentation for swapSizes2D function
Mar 10, 2025
f39c134
Add rotation decision tree picture to repository
Mar 10, 2025
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
25 changes: 18 additions & 7 deletions advisor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,20 @@ std::vector<Transform const *> *Advisor::recommend(
Tristate::Tristate isBatched, Tristate::Tristate isFloat,
Tristate::Tristate isForward, Tristate::Tristate isInPlace,
Tristate::Tristate isReal, int maxSignalInc, int maxMemory,
bool allowTransposition, bool squareOnly, bool crop) {
bool disallowRotation, bool allowTransposition, bool disallowSizeOptimization,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personally I'm not a fan of negated bool variables. I would prefer allowRotation and allowSizeOptimization (multiple occurrences).
This would also require changes in the inputParser and main.cpp

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand your reasoning. Why did I choose to use negated bool variable is because I wanted "rotation" to be enabled by default in the cuFFTAdvisor. Same goes for disallowSizeOptimization (new option to disable cropping/padding). I think, it is a nice addition for the tool, however, as size change is the main focus, the only possibility to add this option is by negating it as "disallow" and having SizeOptimization enabled until user chooses to disable it.

int countOfOptimizedDimensions, bool squareOnly, bool crop) {
Validator::validate(device);
maxMemory = getMaxMemory(device, maxMemory);
Validator::validate(x, y, z, n, device, maxSignalInc, maxMemory, allowTransposition, squareOnly);
Validator::validate(x, y, z, n, device, maxSignalInc, maxMemory,
countOfOptimizedDimensions, allowTransposition, squareOnly);
GeneralTransform tr = GeneralTransform(device, x, y, z, n, isBatched, isFloat,
isForward, isInPlace, isReal);

SizeOptimizer optimizer(CudaVersion::V_8, tr, allowTransposition);
SizeOptimizer optimizer(CudaVersion::V_12, tr, allowTransposition);
std::vector<const Transform *> *result =
optimizer.optimize(howMany, maxSignalInc, maxMemory, squareOnly, crop);
optimizer.optimize(howMany, maxSignalInc, maxMemory, disallowRotation,
disallowSizeOptimization, countOfOptimizedDimensions,
squareOnly, crop);
return result;
}

Expand All @@ -45,11 +49,13 @@ std::vector<BenchmarkResult const *> *Advisor::find(
Tristate::Tristate isBatched, Tristate::Tristate isFloat,
Tristate::Tristate isForward, Tristate::Tristate isInPlace,
Tristate::Tristate isReal, int maxSignalInc, int maxMemory,
bool allowTransposition, bool squareOnly, bool crop) {
bool disallowRotation, bool allowTransposition, bool disallowSizeOptimization,
int countOfOptimizedDimensions, bool squareOnly, bool crop) {
std::vector<Transform const *> *candidates =
recommend(howMany, device, x, y, z, n, isBatched, isFloat, isForward,
isInPlace, isReal, maxSignalInc, maxMemory, allowTransposition,
squareOnly, crop);
isInPlace, isReal, maxSignalInc, maxMemory, disallowRotation,
allowTransposition, disallowSizeOptimization,
countOfOptimizedDimensions, squareOnly, crop);
std::vector<BenchmarkResult const *> *result = benchmark(*candidates);
std::sort(result->begin(), result->end(), BenchmarkResult::execSort);
delete candidates;
Expand All @@ -61,6 +67,11 @@ std::vector<BenchmarkResult const *> *Advisor::benchmark(
std::vector<BenchmarkResult const *> *results =
new std::vector<BenchmarkResult const *>();
int size = transforms.size();

if (transforms.size() > 0) {
Benchmarker::benchmark(transforms.at(0));
}

for (int i = 0; i < size; i++) {
results->push_back(Benchmarker::benchmark(transforms.at(i)));
}
Expand Down
6 changes: 6 additions & 0 deletions advisor.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ class Advisor {
Tristate::Tristate isInPlace = Tristate::TRUE,
Tristate::Tristate isReal = Tristate::TRUE, int maxSignalInc = INT_MAX,
int maxMemory = INT_MAX,
bool disallowRotation = false,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double negation (see my comment above)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answered in comment #15 (comment)

bool allowTransposition = false,
bool disallowSizeOptimization = false,
int countOfOptimizedDimensions = MaxNumberOfOptimizedDimensions,
bool squareOnly = false,
bool crop = false);

Expand All @@ -37,7 +40,10 @@ class Advisor {
Tristate::Tristate isInPlace = Tristate::TRUE,
Tristate::Tristate isReal = Tristate::TRUE, int maxSignalInc = INT_MAX,
int maxMemory = INT_MAX,
bool disallowRotation = false,
bool allowTransposition = false,
bool disallowSizeOptimization = false,
int countOfOptimizedDimensions = MaxNumberOfOptimizedDimensions,
bool squareOnly = false,
bool crop = false);

Expand Down
21 changes: 20 additions & 1 deletion generalTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ GeneralTransform::GeneralTransform(int device, int X, int Y, int Z, int N,
X(X),
Y(Y),
Z(Z),
originalX(X),
originalY(Y),
originalZ(Z),
N(N),
kernelInvocationX(0),
kernelInvocationY(0),
kernelInvocationZ(0),
isBatched(isBatched),
isFloat(isFloat),
isForward(isForward),
Expand All @@ -25,14 +31,24 @@ GeneralTransform::GeneralTransform(int X, int Y, int Z,
X(X),
Y(Y),
Z(Z),
originalX(X),
originalY(Y),
originalZ(Z),
N(tr.N),
kernelInvocationX(0),
kernelInvocationY(0),
kernelInvocationZ(0),
isBatched(tr.isBatched),
isFloat(tr.isFloat),
isForward(tr.isForward),
isInPlace(tr.isInPlace),
isReal(tr.isReal) {}

GeneralTransform::GeneralTransform(const GeneralTransform &tr) { *this = tr; }
GeneralTransform::GeneralTransform(const GeneralTransform &tr)
: originalX(tr.originalX),
originalY(tr.originalY),
originalZ(tr.originalZ)
{ *this = tr; }

GeneralTransform &GeneralTransform::operator=(const GeneralTransform &tr) {
if (this != &tr) {
Expand All @@ -46,6 +62,9 @@ GeneralTransform &GeneralTransform::operator=(const GeneralTransform &tr) {
this->isForward = tr.isForward;
this->isInPlace = tr.isInPlace;
this->isReal = tr.isReal;
this->kernelInvocationX = tr.kernelInvocationX;
this->kernelInvocationY = tr.kernelInvocationY;
this->kernelInvocationZ = tr.kernelInvocationZ;
}
return *this;
}
Expand Down
9 changes: 9 additions & 0 deletions generalTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ class GeneralTransform {
Tristate::Tristate isInPlace; // otherwise out-of-place
Tristate::Tristate isReal; // otherwise C2C

const int originalX;
const int originalY;
const int originalZ;

// number of kernel invocations for selected dimension
// the number of kernel invocations is decided separately for each dimension
int kernelInvocationX;
int kernelInvocationY;
int kernelInvocationZ;
};

} // namespace cuFFTAdvisor
Expand Down
37 changes: 37 additions & 0 deletions inputParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ InputParser::InputParser(int argc, char **argv) {
maxSignalInc = parseMaxSignalInc();
maxMemMB = parseMaxMemMB();
allowTransposition = parseAllowTransposition();
disallowRotation = parseDisallowRotation();
disallowSizeOptimization = parseDisallowSizeOptimization();
countOfOptimizedDimensions = parseCountOfOptimizedDimensions();
squareOnly = parseSquareOnly();
crop = parseCrop();
}
Expand Down Expand Up @@ -58,6 +61,20 @@ int InputParser::parseMaxMemMB() {
return INT_MAX;
}

int InputParser::parseCountOfOptimizedDimensions() {
for (int i = 0; i < (argc - 1); i++) {
if (safeEquals(argv[i], "--countOfOptimizedDimensions")) {
if (NULL == argv[i + 1]) {
return -1;
}
int count = atoi(argv[i + 1]);
argv[i] = argv[i + 1] = NULL;
return count;
}
}
return MaxNumberOfOptimizedDimensions;
}

bool InputParser::reportUnparsed(FILE *stream) {
bool error = false;
if (NULL != stream) {
Expand Down Expand Up @@ -195,6 +212,26 @@ bool InputParser::parseAllowTransposition() {
return false;
}

bool InputParser::parseDisallowRotation() {
for (int i = 0; i < argc; i++) {
if (safeEquals(argv[i], "--disallowRotation")) {
argv[i] = NULL;
return true;
}
}
return false;
}

bool InputParser::parseDisallowSizeOptimization() {
for (int i = 0; i < argc; i++) {
if (safeEquals(argv[i], "--disallowSizeOptimization")) {
argv[i] = NULL;
return true;
}
}
return false;
}

bool InputParser::parseSquareOnly() {
for (int i = 0; i < argc; i++) {
if (safeEquals(argv[i], "--squareOnly")) {
Expand Down
6 changes: 6 additions & 0 deletions inputParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ class InputParser {
int maxSignalInc;
int maxMemMB;
bool allowTransposition;
bool disallowRotation;
bool disallowSizeOptimization;
int countOfOptimizedDimensions;
bool squareOnly;
bool crop;
Tristate::Tristate isBatched;
Expand All @@ -35,6 +38,9 @@ class InputParser {
int parseMaxSignalInc();
int parseMaxMemMB();
bool parseAllowTransposition();
bool parseDisallowRotation();
bool parseDisallowSizeOptimization();
int parseCountOfOptimizedDimensions();
bool parseSquareOnly();
bool parseCrop();
Tristate::Tristate parseIsReal();
Expand Down
22 changes: 18 additions & 4 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ int printHelp() {
"(swapping dimensions). Prohibited by default. Valid for "
"'-find' only."
<< std::endl;
std::cout << "\t--disallowRotation : consider also rotation of X and Y axes "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the difference between rotation and transposition?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fundamentally, there is no difference (both do the same - swap the sizes), however, each swap is programmed differently:

  1. new "Rotation" is allowed by default and swap is based on heuristic
  2. old "Transposition" is prohibited by default and just copy all possible configurations with swapped dimensions

To preserve backward compatibility, I chose to add new parameter instead of reusing already used.

In your opinion, is it good or bad approach?

"(swapping dimensions). Allowed by default."
<< std::endl;
std::cout << "\t--disallowSizeOptimization : disable size optimization by padding/cropping. "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If no padding / cropping is allowed, what other option is there for performance improvement, except for transposition?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is not padding/cropping, but user will still receive optimalized configuration (i.e. float, R2R, etc.). Also, I believe, there could be usecases for this type of transformation.

"Allowed by default."
<< std::endl;
std::cout << "\t--squareOnly : consider only square shapes "
"(X dimension size will be used as a starting point). "
"Incompatible with --allowTransposition."
Expand All @@ -61,6 +67,9 @@ int printHelp() {
std::cout << "\t--maxMem MB : max memory (in MB) that transformation can "
"use, default = device limit"
<< std::endl;
std::cout << "\t--countOfOptimizedDimensions COUNT : number of size dimensionsthat will be optimized, "
"Default: '3' for 3D signal, '2' for 2D signal, '1' for 1D signal"
<< std::endl;
return -1;
}

Expand Down Expand Up @@ -109,8 +118,11 @@ int parseRecommend(int argc, char **argv, int howMany) {
howMany, parser.device, parser.x, parser.y, parser.z, parser.n,
parser.isBatched, parser.isFloat, parser.isForward,
parser.isInPlace, parser.isReal, parser.maxSignalInc,
parser.maxMemMB, parser.allowTransposition, parser.squareOnly,
parser.crop);
parser.maxMemMB, parser.disallowRotation,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a design flaw of the original code.
If you have time, it would be good to replace this list of parameters by a structure. The same for other functions

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can fix it, however, I would prefer to fix it in different pull request as I dont want to combine pull requests with different focus (adding functionality vs. refactoring). Is it okay?

parser.allowTransposition,
parser.disallowSizeOptimization,
parser.countOfOptimizedDimensions,
parser.squareOnly, parser.crop);

cuFFTAdvisor::Transform::printHeader(stdout);
std::cout << std::endl;
Expand Down Expand Up @@ -142,8 +154,10 @@ int parseFind(int argc, char **argv, int howMany) {
parser.isFloat, parser.isForward,
parser.isInPlace, parser.isReal,
parser.maxSignalInc, parser.maxMemMB,
parser.allowTransposition, parser.squareOnly,
parser.crop);
parser.disallowRotation, parser.allowTransposition,
parser.disallowSizeOptimization,
parser.countOfOptimizedDimensions,
parser.squareOnly, parser.crop);

cuFFTAdvisor::BenchmarkResult::printHeader(stdout);
std::cout << std::endl;
Expand Down
Binary file added rotation_decision_tree_marked_leaves.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading