简体   繁体   中英

Speeding up Python with C++

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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM