As I wrote in my previous topic: Benchmarking code - am I doing it right? I need to find a way to get benchmark statistics, like average, mean, standard deviation, etc. How can I do this using those methods I posted? Notice that I use a solution to benchmark code with time interval, not by calling a function many times. Any ideas?
I came up with just one, dont know if its correct (pseudocode):
buffsize = 1024;
buffer [buffsize];
totalcycles = 0
// arrays
walltimeresults = []
cputimeresults = []
// benchmarking
for i in (0, iterations):
start = walltime();
fun2measure(args, buffer);
end = walltime();
walltimeresults[i] = end - start;
start = cputime();
fun2measure(args, buffer);
end = cputime();
cputimeresults[i] = end - start;
c1 = cyclecount();
fun2measure(args, buffer);
c2 = cyclecount();
cyclesperbyte = c2-c1/(buffsize);
totalcycles += cyclesperbyte;
for i in range (0, iterations) : sum += walltimeresults[i];
avg_wall_time = sum / iterations;
sum = 0;
for i in range (0, iterations) : sum += cputimeresults[i];
avg_cpu_time = sum / iterations;
avg_cycles = totalcycles / iterations;
Is it correct? How about mean, standard deviation, etc?
Your average looks OK.
Mean (i.e. average) is
mean = 1/N * sum( x[i] )
Standard deviation is square root of variance:
sigma = sqrt( 1/N * sum( (x[i]-mean)^2 )
Related
I've been learning about LuaJIT and the Lua FFI library using Love 2D. To test if FFI was really faster, I coded a function to count all prime numbers in a range.
(Code probably isn't accurate, I just wanted a hard math problem that both languages could get the same answer on)
// test.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double numberBuffer;
double getPrimes(double n) {
double count = 0;
for (double i = 1; i <= n; i++) {
double cap = pow(i, 0.5);
for (double num = 2; num <= cap; num++) {
if (fmod(i, num) == 0) {
count++;
break;
}
}
}
numberBuffer = count;
return numberBuffer;
}
-- main.lua
local ffi = require("ffi")
function loadFFI(name)
local dir = love.filesystem.getRealDirectory("bin/" .. name .. ".so")
return ffi.load(dir .. "bin/" .. name .. ".so")
end
local test = loadFFI("test")
ffi.cdef[[
double getPrimes(double n);
]]
local function getPrimes(n)
local count = 0
for i = 1,n do
for num = 2, i^(0.5) do
if (i % num) == 0 then
count = (count + 1)
break
end
end
end
return count
end
function love.load()
local one, two = 0, 0
local n = 60000
local time = love.timer.getTime()
local c = test.getPrimes(n)
one = (love.timer.getTime() - time)
time = love.timer.getTime()
local lua = getPrimes(n)
two = (love.timer.getTime() - time)
print("n = " .. tostring(n))
print("C", c, (tostring(one * 1000) .. " miliseconds"))
print("Lua", lua, (tostring(two * 1000) .. " miliseconds"))
end
At first the results were as I expected. With small sets, Lua is faster, I assume because of overhead. With slightly larger sets, C becomes much faster.
With very large sets however, C becomes much slower. Why?
Thanks to Ikegami for answering in comments.
Changing the doubles to ints, and replacing fmod with the % operator solved the issue.
I am wondering about that you not using love.graphics.print() in love.draw()...
-- main.lua
local ffi = require("ffi")
local test = ffi.load("./test.so")
ffi.cdef[[
int getPrimes(int n);
]]
local function getPrimes(n)
local count = 0
for i = 1,n do
for num = 2, i^(0.5) do
if (i % num) == 0 then
count = (count + 1)
break
end
end
end
return count
end
local one, two, n, time, c, lua = 0, 0, 60000, 0, 0, 0
function love.update()
time = love.timer.getTime()
c = test.getPrimes(n)
one = (love.timer.getTime() - time)
time = love.timer.getTime()
lua = getPrimes(n)
two = (love.timer.getTime() - time)
end
function love.draw()
love.graphics.print("n\t" .. tostring(n), 100, 100)
love.graphics.print("C\t" .. c .. "\t" .. (tostring(one * 1000) .. " miliseconds"), 100, 200)
love.graphics.print("Lua\t" .. lua .. "\t" .. (tostring(two * 1000) .. " miliseconds"), 100, 300)
end
I'm trying to figure out why the time complexity of this code is n2/3. The space complexity is log n, but I don't know how to continue the time complexity calculation (or if it's right).
int g2 (int n, int m)
{
if (m >= n)
{
for (int i = 0; i < n; ++i)
printf("#");
return 1;
}
return 1 + g2 (n / 2, 4 * m);
}
int main (int n)
{
return g2 (n, 1);
}
As long as m < n, you perform an O(1) operation: making a recursive call. You halve n and quadruple m, so after k steps, you get
n(k) = n(0) * 0.5^k
m(k) = m(0) * 4^k
You can set them equal to each other to find that
n(0) / m(0) = 8^k
Taking the log
log(n(0)) - log(m(0)) = k log(8)
or
k = log_8(n(0)) - log_8(m(0))
On the kth recursion you perform n(k) loop iterations.
You can plug k back into n(k) = n(0) * 0.5^k to estimate the number of iterations. Let's ignore m(0) for now:
n(k) = n(0) * 0.5^log_8(n(0))
Taking again the log of both sides,
log_8(n(k)) = log_8(n(0)) + log_8(0.5) * log_8(n(0))
Since log_8(0.5) = -1/3, you get
log_8(n(k)) = log_8(n(0)) * (2/3)`
Taking the exponent again:
n(k) = n(0)^(2/3)
Since any positive exponent will overwhelm the O(log(n)) recursion, your final complexity is indeed O(n^(2/3)).
Let's look for a moment what happens if m(0) > 1.
n(k) = n(0) * 0.5^(log_8(n(0)) - log_8(m(0)))
Again taking the log:
log_8(n(k)) = log_8(n(0)) - 1/3 * (log_8(n(0)) - log_8(m(0)))
log_8(n(k)) = log_8(n(0)^(2/3)) + log_8(m(0)^(1/3))
So you get
n(k) = n(0)^(2/3) * m(0)^(1/3)
Or
n(k) = (m n^2)^(1/3)
Quick note on corner cases in the starting conditions:
For m > 0:
If n <= 0:, n <= m is immediately true and the recursion terminates and there is no loop.
For m < 0:
If n <= m, the recursion terminates immediately and there is no loop. If n > m, n will converge to zero while m diverges, and the algorithm will run forever.
The only interesting case is where m == 0. Regardless of whether n is positive or negative, it will reach zero because of integer truncation, so the complexity depends on when it reaches 1:
n(0) * 0.5^k = 1
log_2(n(0)) - k = 0
So in this case, the runtime of the recursion is still O(log(n)). The loop does not run.
m starts at 1, and at each step n -> n/2 and m -> m*4 until m>n. After k steps, n_final = n/2^k and m_final = 4^k. So the final value of k is where n/2^k = 4^k, or k = log8(n).
When this is reached, the inner loop performs n_final (approximately equal to m_final) steps, leading to a complexity of O(4^k) = O(4^log8(n)) = O(4^(log4(n)/log4(8))) = O(n^(1/log4(8))) = O(n^(2/3)).
I have a problem that, after much head scratching, I think is to do with very small numbers in a long-double.
I am trying to implement Planck's law equation to generate a normalised blackbody curve at 1nm intervals between a given wavelength range and for a given temperature. Ultimately this will be a function accepting inputs, for now it is main() with the variables fixed and outputting by printf().
I see examples in matlab and python, and they are implementing the same equation as me in a similar loop with no trouble at all.
This is the equation:
My code generates an incorrect blackbody curve:
I have tested key parts of the code independently. After trying to test the equation by breaking it into blocks in excel I noticed that it does result in very small numbers and I wonder if my implementation of large numbers could be causing the issue? Does anyone have any insight into using C to implement equations? This a new area to me and I have found the maths much harder to implement and debug than normal code.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
//global variables
const double H = 6.626070040e-34; //Planck's constant (Joule-seconds)
const double C = 299800000; //Speed of light in vacume (meters per second)
const double K = 1.3806488e-23; //Boltzmann's constant (Joules per Kelvin)
const double nm_to_m = 1e-6; //conversion between nm and m
const int interval = 1; //wavelength interval to caculate at (nm)
//typedef structure to hold results
typedef struct {
int *wavelength;
long double *radiance;
long double *normalised;
} results;
int main() {
int min = 100 , max = 3000; //wavelength bounds to caculate between, later to be swaped to function inputs
double temprature = 200; //temprature in kelvin, later to be swaped to function input
double new_valu, old_valu = 0;
static results SPD_data, *SPD; //setup a static results structure and a pointer to point to it
SPD = &SPD_data;
SPD->wavelength = malloc(sizeof(int) * (max - min)); //allocate memory based on wavelength bounds
SPD->radiance = malloc(sizeof(long double) * (max - min));
SPD->normalised = malloc(sizeof(long double) * (max - min));
for (int i = 0; i <= (max - min); i++) {
//Fill wavelength vector
SPD->wavelength[i] = min + (interval * i);
//Computes radiance for every wavelength of blackbody of given temprature
SPD->radiance[i] = ((2 * H * pow(C, 2)) / (pow((SPD->wavelength[i] / nm_to_m), 5))) * (1 / (exp((H * C) / ((SPD->wavelength[i] / nm_to_m) * K * temprature))-1));
//Copy SPD->radiance to SPD->normalised
SPD->normalised[i] = SPD->radiance[i];
//Find largest value
if (i <= 0) {
old_valu = SPD->normalised[0];
} else if (i > 0){
new_valu = SPD->normalised[i];
if (new_valu > old_valu) {
old_valu = new_valu;
}
}
}
//for debug perposes
printf("wavelength(nm) radiance(Watts per steradian per meter squared) normalised radiance\n");
for (int i = 0; i <= (max - min); i++) {
//Normalise SPD
SPD->normalised[i] = SPD->normalised[i] / old_valu;
//for debug perposes
printf("%d %Le %Lf\n", SPD->wavelength[i], SPD->radiance[i], SPD->normalised[i]);
}
return 0; //later to be swaped to 'return SPD';
}
/*********************UPDATE Friday 24th Mar 2017 23:42*************************/
Thank you for the suggestions so far, lots of useful pointers especially understanding the way numbers are stored in C (IEEE 754) but I don't think that is the issue here as it only applies to significant digits. I implemented most of the suggestions but still no progress on the problem. I suspect Alexander in the comments is probably right, changing the units and order of operations is likely what I need to do to make the equation work like the matlab or python examples, but my knowledge of maths is not good enough to do this. I broke the equation down into chunks to take a closer look at what it was doing.
//global variables
const double H = 6.6260700e-34; //Planck's constant (Joule-seconds) 6.626070040e-34
const double C = 299792458; //Speed of light in vacume (meters per second)
const double K = 1.3806488e-23; //Boltzmann's constant (Joules per Kelvin) 1.3806488e-23
const double nm_to_m = 1e-9; //conversion between nm and m
const int interval = 1; //wavelength interval to caculate at (nm)
const int min = 100, max = 3000; //max and min wavelengths to caculate between (nm)
const double temprature = 200; //temprature (K)
//typedef structure to hold results
typedef struct {
int *wavelength;
long double *radiance;
long double *normalised;
} results;
//main program
int main()
{
//setup a static results structure and a pointer to point to it
static results SPD_data, *SPD;
SPD = &SPD_data;
//allocate memory based on wavelength bounds
SPD->wavelength = malloc(sizeof(int) * (max - min));
SPD->radiance = malloc(sizeof(long double) * (max - min));
SPD->normalised = malloc(sizeof(long double) * (max - min));
//break equasion into visible parts for debuging
long double aa, bb, cc, dd, ee, ff, gg, hh, ii, jj, kk, ll, mm, nn, oo;
for (int i = 0; i < (max - min); i++) {
//Computes radiance at every wavelength interval for blackbody of given temprature
SPD->wavelength[i] = min + (interval * i);
aa = 2 * H;
bb = pow(C, 2);
cc = aa * bb;
dd = pow((SPD->wavelength[i] / nm_to_m), 5);
ee = cc / dd;
ff = 1;
gg = H * C;
hh = SPD->wavelength[i] / nm_to_m;
ii = K * temprature;
jj = hh * ii;
kk = gg / jj;
ll = exp(kk);
mm = ll - 1;
nn = ff / mm;
oo = ee * nn;
SPD->radiance[i] = oo;
}
//for debug perposes
printf("wavelength(nm) | radiance(Watts per steradian per meter squared)\n");
for (int i = 0; i < (max - min); i++) {
printf("%d %Le\n", SPD->wavelength[i], SPD->radiance[i]);
}
return 0;
}
Equation variable values during runtime in xcode:
I notice a couple of things that are wrong and/or suspicious about the current state of your program:
You have defined nm_to_m as 10-9,, yet you divide by it. If your wavelength is measured in nanometers, you should multiply it by 10-9 to get it in meters. To wit, if hh is supposed to be your wavelength in meters, it is on the order of several light-hours.
The same is obviously true for dd as well.
mm, being the exponential expression minus 1, is zero, which gives you infinity in the results deriving from it. This is apparently because you don't have enough digits in a double to represent the significant part of the exponential. Instead of using exp(...) - 1 here, try using the expm1() function instead, which implements a well-defined algorithm for calculating exponentials minus 1 without cancellation errors.
Since interval is 1, it doesn't currently matter, but you can probably see that your results wouldn't match the meaning of the code if you set interval to something else.
Unless you plan to change something about this in the future, there shouldn't be a need for this program to "save" the values of all calculations. You could just print them out as you run them.
On the other hand, you don't seem to be in any danger of underflow or overflow. The largest and smallest numbers you use don't seem to be a far way from 10±60, which is well within what ordinary doubles can deal with, let alone long doubles. The being said, it might not hurt to use more normalized units, but at the magnitudes you currently display, I wouldn't worry about it.
Thanks for all the pointers in the comments. For anyone else running into a similar problem with implementing equations in C, I had a few silly errors in the code:
writing a 6 not a 9
dividing when I should be multiplying
an off by one error with the size of my array vs the iterations of for() loop
200 when I meant 2000 in the temperature variable
As a result of the last one particularly I was not getting the results I expected (my wavelength range was not right for plotting the temperature I was calculating) and this was leading me to the assumption that something was wrong in the implementation of the equation, specifically I was thinking about big/small numbers in C because I did not understand them. This was not the case.
In summary, I should have made sure I knew exactly what my equation should be outputting for given test conditions before implementing it in code. I will work on getting more comfortable with maths, particularly algebra and dimensional analysis.
Below is the working code, implemented as a function, feel free to use it for anything but obviously no warranty of any kind etc.
blackbody.c
//
// Computes radiance for every wavelength of blackbody of given temprature
//
// INPUTS: int min wavelength to begin calculation from (nm), int max wavelength to end calculation at (nm), int temperature (kelvin)
// OUTPUTS: pointer to structure containing:
// - spectral radiance (Watts per steradian per meter squared per wavelength at 1nm intervals)
// - normalised radiance
//
//include & define
#include "blackbody.h"
//global variables
const double H = 6.626070040e-34; //Planck's constant (Joule-seconds) 6.626070040e-34
const double C = 299792458; //Speed of light in vacuum (meters per second)
const double K = 1.3806488e-23; //Boltzmann's constant (Joules per Kelvin) 1.3806488e-23
const double nm_to_m = 1e-9; //conversion between nm and m
const int interval = 1; //wavelength interval to calculate at (nm), to change this line 45 also need to be changed
bbresults* blackbody(int min, int max, double temperature) {
double new_valu, old_valu = 0; //variables for normalising result
bbresults *SPD;
SPD = malloc(sizeof(bbresults));
//allocate memory based on wavelength bounds
SPD->wavelength = malloc(sizeof(int) * (max - min));
SPD->radiance = malloc(sizeof(long double) * (max - min));
SPD->normalised = malloc(sizeof(long double) * (max - min));
for (int i = 0; i < (max - min); i++) {
//Computes radiance for every wavelength of blackbody of given temperature
SPD->wavelength[i] = min + (interval * i);
SPD->radiance[i] = ((2 * H * pow(C, 2)) / (pow((SPD->wavelength[i] * nm_to_m), 5))) * (1 / (expm1((H * C) / ((SPD->wavelength[i] * nm_to_m) * K * temperature))));
//Copy SPD->radiance to SPD->normalised
SPD->normalised[i] = SPD->radiance[i];
//Find largest value
if (i <= 0) {
old_valu = SPD->normalised[0];
} else if (i > 0){
new_valu = SPD->normalised[i];
if (new_valu > old_valu) {
old_valu = new_valu;
}
}
}
for (int i = 0; i < (max - min); i++) {
//Normalise SPD
SPD->normalised[i] = SPD->normalised[i] / old_valu;
}
return SPD;
}
blackbody.h
#ifndef blackbody_h
#define blackbody_h
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
//typedef structure to hold results
typedef struct {
int *wavelength;
long double *radiance;
long double *normalised;
} bbresults;
//function declarations
bbresults* blackbody(int, int, double);
#endif /* blackbody_h */
main.c
#include <stdio.h>
#include "blackbody.h"
int main() {
bbresults *TEST;
int min = 100, max = 3000, temp = 5000;
TEST = blackbody(min, max, temp);
printf("wavelength | normalised radiance | radiance |\n");
printf(" (nm) | - | (W per meter squr per steradian) |\n");
for (int i = 0; i < (max - min); i++) {
printf("%4d %Lf %Le\n", TEST->wavelength[i], TEST->normalised[i], TEST->radiance[i]);
}
free(TEST);
free(TEST->wavelength);
free(TEST->radiance);
free(TEST->normalised);
return 0;
}
Plot of output:
I have a code that is supposed to do the following:
The first function called on, named CalcNum1.m, will find the sum of all the
values in any sized array using a for loop instead of the sum function. This sum divided
by 2 will be saved to the variable Num1.
Finally, in the second function named PrintTerms.m, reorder your terms using the
built in sort function. Now, find how many terms (starting with the first and the
smallest), when adding upon one another, are necessary to surpass the value of Num1.
Print to the user how many terms are necessary.
Here is my code for the main script:
B = input ('Enter matrix B');
[Num1,sum] = CalcNum1(B);
[Q] = PrintTerms(B, Num1);
And here is my code for the functions
function [sum, Num1] = CalcNum1(B)
n = numel(B);
sum1 =0;
for i = 1:n
sum1 = sum1 + B(i);
end
sum = sum1;
Num1 = sum/2;
end
function [Q] = PrintTerms( B, Num1 )
sort (B)
sum1 = 0;
i = 0;
count = 0;
while sum1<=Num1
i = i+1
sum1 = sum1 + B(i)
count = count+1
end
Q = count;
sum1
fprintf(' This many terms necessary %.2f',Q)
end
Try:
function [Num1, my_sum] = CalcNum1(B)
n = numel(B);
my_sum =0;
for i = 1:n
my_sum = my_sum + B(i);
end
Num1 = my_sum/2;
end
Note that I switched the output order, as you call it [Num1,sum] =
function count = PrintTerms( B, Num1 ) % No need for brackets when only single output
B = sort(B); % Need to save it in a new (or the same variable)
% sort(B) will only print the sorted vector
my_sum = 0;
ii = 0;
count = 0;
while my_sum <= Num1
ii = ii+1; % Use semicolons to supress output
my_sum = my_sum + B(ii);
count = count + 1; % Use space for better readability
end
fprintf(' This many terms necessary %.2f \n', count)
% Include \n to get a line shift
end
Use brackets when you type in B, like this: [1 2 3 4 2 3 4 23 12 32 12 2 3 6]
If you want it simpler, you could also use cumsum and avoid the loops. This is your entire last function (except the print part):
vec_sum = cumsum(sort(B)); % See documentation for explanation
count = find(vec_sum >= Num1,1) ; % the second input 1, is to only include the
% first element larger than Num1
Your PrintTerms function seems to work well. As possible problem is that, asuming Num1 is an arbitrary value, if it's so large that it's not reached even with all elements of B, you will try to pull a non-existent further element from B. To avoid that you can add a condition with if and a flag result to indicate whether you had success or not:
% [...]
success = 1; % for now
while (sum1 <= Num1)
ii = ii+1; % Use semicolons to supress output
if ii>length(B)
success = 0; % we ran out of terms
break; % exit while loop
end
sum1 = sum1 + B(ii);
count = count + 1; % Use space for better readability
end
if success
fprintf(' This many terms necessary %.2f', count)
else
fprintf(' The sum cannot be reached')
end
Also, note that sort(B) does not store the result. Use B = sort(B);
I'm really confused on this code.
Here's what I want it to do: Start with a "v" value of 5, carry out the rest of the functions/calculations, increase the "v" value by 0.01, carry out the functions/calculations, then increase the "v" value by 0.01 again, carry out the functions...do this 500 times or until a "v" value of 10.00 is reached, whichever is easier to code.
Here is my code at the moment:
//start loop over v
for(iv=5;iv<=500;iv++) {
v=0.01*iv;
//Lots and lots of calculations with v here
}
Here is what I get: I tried setting iv<=10 so it does 10 loops only just so I could test it first before leaving it on all night. It did only 6 loops, starting at v=0.05 and ending at 0.1. So the problem is that a) it didn't run for 10 loops, b) it didn't start at 5.00, it started at 0.05.
Any help would be appreciated.
EDIT: Holy crap, so many answers! I've tried 2 different answers so far, both work! I've been staring at this and changing code around for 3 hours, can't believe it was so easy.
You need to start at iv = 500. and if you want 10 loops, and iv++ is the update, then you stop before 510.
Reason: v = 0.01*iv, so v = 5 means iv = 5/0.01 = 500. As for the number of iterations, if your for loop is of the form for (x = N; x < M; x++) (constant N and M), then max(0, M-N) loops are executed, if x is not changed in the loop and no weird stuff (e.g. overflow, hidden casts of negative numbers to unsigned, etc.) occurs.
EDIT
Instead of using v = 0.01 * iv, v = iv / 100.0 is probably more accurate. Reason: 0.01 is not exactly representable in floating point, but 100.0 is.
Changing SiegeX's code so it uses integers ("more accurate"):
double dv;
int iv;
for(iv = 500; dv <= 1000; iv += 1)
{
dv = (double)iv / 100.0;
}
double iv;
for(iv = 5.0; iv <= 10.0 ; iv += 0.01) {
/* stuff here */
}
int i;
double v;
v = 5;
for (i = 0; i < 500; i++)
{
v += 0.01;
// Do Calculations Here.
if (v >= 10.00) break;
}
This gives you both. This will iterate at most 500 times, but will break out of that loop if the v value reaches (or exceeds) 10.00.
If you wanted only one or the other:
The 10.00 Version:
double v;
v = 5.0;
while ( v < 10.00 )
{
v += 0.01;
// Do Calculations Here.
}
The 500 iterations version:
double v;
int i;
v = 5.0;
for( i = 0; i < 500; i++ )
{
v += 0.01;
// Do Calculations.
}
(Note that this isn't C99, which allows for a cleaner declaration syntax in the loops).
iv <= 10 doesn't do it for 10 loops, it does it until iv is greater than 10.
//start loop over v
for(iv=0;iv<500;iv++) //loop from 0 to 499
{
v=v+0.01; //increase v by 0.01
//Lots and lots of calculations with v here
}
this should do it