-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement runs inside threads #67
Conversation
benchmark/main.cpp
Outdated
@@ -170,7 +189,7 @@ int main(int argc, char* argv[]) { | |||
Flags flags; | |||
flags.Var(colCount, 'c', "column-count", 1, "Number of columns to use"); | |||
flags.Var(threadCount, 't', "thread-count", 1, "Number of threads"); | |||
flags.Var(iterations, 'i', "iterations", 6, "Number of iterations"); | |||
flags.Var(iterations, 'i', "iterations", -1, "Number of iterations"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you use 0, you don't need this check iterations==-1 below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still gonna need the check, but I can change it to 0 if you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You still need the check but it would look like:
int mIterations = iterations ? iterations : max(1, (int) (1 / ITERATIONS_FACTOR / size * 8 * KiB));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't really like that, it should be immediately clear iterations is a number... I changed it to 0 now.
benchmark/main.cpp
Outdated
for (auto size: DB_SIZES){ | ||
cerr << "benchmarking " << (size / 1024.0f) << " KiB" << endl; | ||
|
||
int mIterations = iterations == -1 ? max(1, (int) (1 / ITERATIONS_FACTOR / size * 8 * KiB)) : iterations; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#Insert useful comment here and intuition behind
int mIterations = iterations ? iterations : max(1, (int) (1 / ITERATIONS_FACTOR / size * 8 * KiB));
benchmark/main.cpp
Outdated
for (auto size: DB_SIZES){ | ||
cerr << "benchmarking " << (size / 1024.0f) << " KiB" << endl; | ||
|
||
// For smallest size, iterations will be 1 / factor, e.g. 1/0.01 = 100. For double the size half of that etc. | ||
int mIterations = iterations == 0 ? max(1, (int) (1 / ITERATIONS_FACTOR / size * DB_SIZES[0])) : iterations; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still find this super confusing. Why are we using the reciprocal value and not a multiplicative factor? Alternatively, we could define a minimum amount of data to be benchmarked against.
Also, what does the m
in mIterations
stand for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that a reciprocal value is not really intuitive.
But the greater problem I see is that with the current setting we will run the benchmark only once for DB_SIZES > 1 MB. Therefore I would propose (6 iterations like before as a minimum):
iterations = iterations == 0 ? max(6, (int) (ITERATIONS_FACTOR / size * DB_SIZES[0])) : iterations;
with ITERATIONS_FACTOR = 100.0f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't like to overwrite iterations just rename it, maybe dynamic or modified Iterations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Always 6 at least? Ok sure, why not. I thought reciprocal value would be more intuitive, but I can change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I'm not overwriting iterations is that otherwise iterations == 0
will fail in successive loops. Will rename it.
benchmark/main.cpp
Outdated
while (!threads.empty()) { | ||
delete threads.back(); | ||
threads.pop_back(); | ||
} | ||
threadFlag = false; | ||
} | ||
|
||
printResults<T>(times, colSize, threadCount, cache); | ||
size_t startIndex = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line 147-145 is exactly the same as 126-144.
I am quite confused why/ if this is necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I simply moved it from the cache iteration the way it was before. As far as I could tell, the cache was being cleared, followed by a dry-run of reading without using the time measured. The reason I'm not using a for loop with 2 iterations was that I thought it would make the code more obtuse than saving 10 lines was worth.
benchmark/main.cpp
Outdated
} | ||
// Cache clearing, do one dry run after | ||
if (!cache) { | ||
clearCache(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cache clearing has only an effect for the first iteration.
If we still want to use cache clearing it has to be performed in threadFunc.
But that would make our benchmark extremely slow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was my thought as well. Can I remove it then?
benchmark/main.cpp
Outdated
for (auto size: DB_SIZES){ | ||
cerr << "benchmarking " << (size / 1024.0f) << " KiB" << endl; | ||
|
||
// For smallest size, iterations will be 1 / factor, e.g. 1/0.01 = 100. For double the size half of that etc. | ||
int mIterations = iterations == 0 ? max(1, (int) (1 / ITERATIONS_FACTOR / size * DB_SIZES[0])) : iterations; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that a reciprocal value is not really intuitive.
But the greater problem I see is that with the current setting we will run the benchmark only once for DB_SIZES > 1 MB. Therefore I would propose (6 iterations like before as a minimum):
iterations = iterations == 0 ? max(6, (int) (ITERATIONS_FACTOR / size * DB_SIZES[0])) : iterations;
with ITERATIONS_FACTOR = 100.0f
benchmark/main.cpp
Outdated
for (auto size: DB_SIZES){ | ||
cerr << "benchmarking " << (size / 1024.0f) << " KiB" << endl; | ||
|
||
// For smallest size, iterations will be 1 / factor, e.g. 1/0.01 = 100. For double the size half of that etc. | ||
int mIterations = iterations == 0 ? max(1, (int) (1 / ITERATIONS_FACTOR / size * DB_SIZES[0])) : iterations; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't like to overwrite iterations just rename it, maybe dynamic or modified Iterations
Ready to merge, please rereview |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, although the missing cache attribute might break the plots script
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, we should keep the ability to clear the cache for the single-iteration benchmarks
The results for single-iteration benchmarks are probably not reliable (see current variance in plots with even 6 iterations). Therefore we don't need them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
Runs to be averaged are done inside threads to reduce overhead from syncing threadFlag and some other things on very small vectors. Related to that, the number of runs (if no parameter is specified) defaults to
100 / (size / 8KiB)
, so the smallest size will do 100 iterations, the second smallest one 50 etc. I'm still returning one time for each iteration so that we can use error bars.Cache Clearing is kind of irrelevant now, so we might remove it? Feedback welcome!
Edit: Cache clearing has just been removed, from code and bash script