使用cython加速python应用程序

时间:2014-02-03 21:52:17

标签: python cython

我在Kivy应用程序中使用以下python代码。 代码工作正常并显示正确的信息,但在计算返回值和显示到屏幕时速度很慢。 我的问题是:

  1. 我可以用C编写函数并使用cython将它合并到我的python程序中。

  2. 如果可以的话,是否会有明显的速度提升或问题出在其他地方?

  3. def offset_back(initial_bet, initial_odds):
    
        returns = []
        new_odds = Decimal(initial_odds)
        while new_odds > 1:
            # calculate tick based on size of odds
            if 50 < new_odds <= 100:
                tick = Decimal("5.0")
            elif 30 < new_odds <= 50:
                tick = Decimal("2.0")
            elif 20 < new_odds <= 30:
                tick = Decimal("1.0")
            elif 10 < new_odds <= 20:
                tick = Decimal("0.5")
            elif 6 < new_odds <= 10:
                tick = Decimal("0.2")
            elif 4 < new_odds <= 6:
                tick = Decimal("0.1")
            elif 3 < new_odds <= 4:
                tick = Decimal(".05")
            elif 2 < new_odds <= 3:
                tick = Decimal(".02")
            elif new_odds <= 2:
                tick = Decimal(".01")
            else:
                    tick = Decimal("10")
    
            #  calculate percentage difference between initial bet and new odds
            drop = Decimal(100 - (100 * Decimal(initial_odds) / Decimal(new_odds))) / 100
            # calculate amount needed to increase bet by to cancel liability
            increase = abs((initial_bet * drop))
            # calculate new stake
            new_bet = (initial_bet + increase)
            # calculate potential profit based on the new stake - initial invested stake
            profit = (new_bet - initial_bet)
            returns.append(" Stake: %.2f" % abs(new_bet)+ " " * spacing + "Odds: " "%.2f" % abs(new_odds)+ " " * spacing + "Profit: " "%.2f" % abs(profit))
            new_odds -= tick
        return returns
    

2 个答案:

答案 0 :(得分:2)

第一个建议:

以下是一些建议,尝试将Decimal声明移出循环,只需在添加/减少时引用它们。只要你创建它们一次,它就会快得多。

decimals = [
 Decimal("10")
 ,Decimal("5.0")
 ,Decimal("2.0")
 ,Decimal("1.0")
 ,Decimal("0.5")
 ,Decimal("0.2")
 ,Decimal("0.1")
 ,Decimal(".05")
 ,Decimal(".02")
 ,Decimal(".01")
]

用这样的东西替换if:

if 50 < new_odds <= 100:
    tick = decimals[1]

第二个建议:

是删除if else if ...,因为你不总是进入第一个,如果你需要做更多的比较以获得正确的案例。将if块替换为类似的东西。

thick = decimals[getThick(new_odds)]

getThick应该实现可以转换为索引的公式。我想你的厚函数可以用数学表达。

这里使用bisect_left作为休提出的建议是个好主意,除非你能想出一个通过计算来做到这一点的函数。

第三条建议:

用格式字符串替换该行:

returns.append(" Stake: %.2f %s Odds: %.2f %s Profit: %.2f" % 
               (abs(new_bet), spacing, abs(new_odds), spacing, abs(profit)))

答案 1 :(得分:2)

  1. 避免使用十进制 - 你在这里做的事情都不需要绝对精确。

  2. 将if..then级联转换为使用bisect的二进制查找

  3. 我不清楚你的一些数学知识到底是什么,但我对你在这里使用abs()非常抱歉。你确定那是你想要的吗?

  4. 可能不是一个好主意,但为了演示:我已使用yield语句将函数转换为生成函数;而不是返回一个字符串数组,它一次返回一个字符串。

  5. from bisect import bisect_left
    
    breakpoints = [-1.,  2.,   3.,   4.,   6.,   10.,  20.,  30.,  50.,  100.]
    ticks       = [0.,   0.01, 0.02, 0.05, 0.1,  0.2,  0.5,  1.,   2.,   5.,   10.]
    
    def offset_back(initial_bet, initial_odds, breakpoints=breakpoints, ticks=ticks):
        new_odds = initial_odds
        while new_odds > 1.:
            # calculate tick based on size of odds
            tick = ticks[bisect_left(breakpoints, new_odds)]
            # calculate percentage difference between initial bet and new odds
            drop = 1. - initial_odds / new_odds
            # calculate new stake, increased to cancel liability
            new_bet = initial_bet + abs(initial_bet * drop)   # are you sure abs() is correct here?
            # calculate potential profit based on the new stake - initial invested stake
            profit = new_bet - initial_bet
    
            new_odds -= tick
            yield " Stake: {stake:0.2f}    Odds: {odds:0.2f}    Profit: {profit:0.2f}".format(stake=abs(new_bet), odds=abs(new_odds), profit=abs(profit))