Reputation: 1652
I am attempting to speed up a Python script by using ctypes to outsource some of the heavily lifting to C++.
I have this up and running quite nicely with a small example (returning x^2) but now it is time to set up my function in this configuration.
My question is, how would one write this function of Python code nicely in C++ to ensure its as quick as possible, I would hate to think I might not get any speed increase, simply because of my sub-par C++.
def shortTermEnergy(frame):
return sum( [ abs(x)**2 for x in frame ] ) / len(frame)
I will be passing frame
as an array by using arr = (ctypes.c_int * len(frame))(*frame)
converting it from a list to a nice array for C++
I hope this is the best practice and I am not missing anything glaringly obvious? It's been a long time since I wrote any C++.
Thanks
EDIT
I have gone with this C++ code for the moment, please do let me know if there are ways to improve.
#include <cmath>
extern "C" int square(int size, int array[])
{
int sum = 0;
for (int i = 0; i < size; i++)
{
int number = array[i];
int value = (number * number);
sum = sum + value;
}
return floor(sum / size);
}
Where size
is the len() of the array passed from Python.
Upvotes: 4
Views: 1892
Reputation: 3857
Sorry for not answering your question explicitly, but I think a numpy solution would be a lot easier to realise and can improve the speed almost as good as a C++ snippet:
import numpy as np
frame = np.random.random_sample(10000)
def shortTermEnergy(frame):
return sum( [ abs(x)**2 for x in frame ] ) / len(frame)
>> %timeit shortTermEnergy(frame)
>> 100 loops, best of 3: 4.11 ms per loop
def dot_product(frame):
return np.dot(frame, frame)/frame.size
>> %timeit dot_product(frame):
>> 10000 loops, best of 3: 19.3 µs per loop
Upvotes: 2
Reputation: 16156
I would go with this:
template<class MeanT, class AccumT = MeanT, class IterT>
MeanT mean_squares(IterT start, IterT end) {
AccumT accum = 0;
for (IterT it = start; it != end; ++it) {
accum += *it * *it;
}
return accum / (end - start);
}
I left out the abs
since it's not necessary. But it could be that the compiler is able to optimise unsigned multiplication better.
Using is like this:
double result = mean_squares<double, unsigned long>(array, array + length);
// std::begin(vect), std::end(vect) in case of an STL vector
I hope this helps.
concerning your code: it's probably OK, though I would make the sum
and i
unsigned. You can add const
to the array parameter type, but the compiler most certainly is able to figure that out on its own.
Oh, and I think you should remove that floor
. Integer division does that already.
Upvotes: 2