Home > Back-end >  how to make this javascript for-loop converted to python code with same or faster execution time?
how to make this javascript for-loop converted to python code with same or faster execution time?

Time:09-13

Please help to optimize my python code, I wrote this JS code and tried to convert it to python that I need the execution time comparable to the original code.

The original code follows for-loop in JS, I transferred the code literally by using pure python and numpy but I didn't optimize it well resulting in poor execution time and memory usage.

This code calculates a preset enemy vs player power with -10% difference and do a random roll then get the player winrate. The target is to set the HERO_POWER or ENEMY_POWER atleast in 100000-300000 range.

    '''
##winchance.js##
Original code

var h = 0
var g = 0
var i = char_power 
var l = i*.9
var u = enemy_power   * 1.1
var d = enemy_power   * .9
for (let e = Math.floor(l); e <= i; e  )
for (let t = Math.floor(d); t <= u; t  ) e >= t ? h   : g  
var z = h / (h   g)*100;
return z
}
var out = combat_simulate(parseInt(arguments[2]),parseInt(arguments[3]))
console.log(out)
'''

import subprocess,itertools,math
import numpy as np

def calc_iter(array):
    w=0
    l=0
    for x,y in array:
        if x >= y:
            w  =1
        else:
            l  =1
    return w,l

###inputs###
HERO_POWER=120000
ENEMY_POWER=110000

w=0
l=0
h_l = HERO_POWER * .9
e_h = ENEMY_POWER * 1.1
e_l = ENEMY_POWER * .9
hp = np.arange(math.floor(h_l),math.floor(HERO_POWER))
ep = np.arange(math.floor(e_l),math.floor(e_h))


print('process using itertools')
start_time = time.time()
array = itertools.product(hp,ep)
w,l = calc_iter(array)
print('win rate:{}%'.format(round((w/(w l))*100,2)))
end_time = time.time()
print('time elapsed',end_time-start_time)

print()
print('process using numpy')
start_time = time.time()
x,y = np.meshgrid(hp,ep)
n = x>y
w,l = (np.count_nonzero(n),np.count_nonzero(n==0))
print('win rate:{}%'.format(round((w/(w l))*100,2)))
end_time = time.time()
print('time elapsed',end_time-start_time)

print()
print('process using nodejs')
start_time = time.time()
result = subprocess.run('node winchance.js {} {}'.format(HERO_POWER,ENEMY_POWER),capture_output=True,text=True)
print('win rate:{}%'.format(round(float(result.stdout),2)))
end_time = time.time()
print('time elapsed',end_time-start_time)
########################################
process using itertools
win rate:68.18%
time elapsed 30.484147787094116

process using numpy
win rate:68.18%
time elapsed 2.0294463634490967

process using nodejs
win rate:68.18%
time elapsed 0.799668550491333

CodePudding user response:

This is more succinct but whether it's faster is for OP to measure because the performance is likely to vary depending on CPU/OS and, possibly, Python version. It will also be significantly affected by the number of elements in the list:

def calc_iter(list_):
    w = sum(x >= y for x, y in list_)
    return w, len(list_)-w

CodePudding user response:

upon searching the web, I tried to translate the python function code using 'numba' and it shows faster execution with no additional thing to do on my end in this context.

import math
import numpy as np
import time
import subprocess
import os
from numba import njit

hero_power_list = [120000,130000,140000]
enemy_power_list = [110000,121000,131000]

@njit
def calc_iter_1(array1,array2):
    w=0
    l=0
    for x in array1:
        for y in array2:
            if x >= y:
                w  =1
            else:
                l  =1
    return w,l


print('process using numba')
for x in range(len(hero_power_list)):
    h_l = hero_power_list[x]  * .9
    e_h = enemy_power_list[x] * 1.1
    e_l = enemy_power_list[x] * .9
    hp = np.arange(math.floor(h_l),math.floor(hero_power_list[x]))
    ep = np.arange(math.floor(e_l),math.floor(e_h))

    start_time = time.perf_counter()
    w,l = calc_iter_1(hp,ep)
    # print('win rate:{}%'.format(round((w/(w l))*100,2)))
    end_time = time.perf_counter()
    print('time elapsed:',round(end_time-start_time,2),'sec(s)')


print()
print('process using nodejs')
for x in range(len(hero_power_list)):
    HERO_POWER = hero_power_list[x]
    ENEMY_POWER = enemy_power_list[x]
    start_time = time.perf_counter()
    result = subprocess.run('node winchance.js {} {}'.format(HERO_POWER,ENEMY_POWER),capture_output=True,text=True)
    # print('win rate:{}%'.format(round(float(result.stdout),2)))
    end_time = time.perf_counter()
    print('time elapsed:',round(end_time-start_time,2),'sec(s)')
########################################
process using numba
time elapsed: 0.87 sec(s)
time elapsed: 0.43 sec(s)
time elapsed: 0.52 sec(s)

process using nodejs
time elapsed: 0.81 sec(s)
time elapsed: 1.07 sec(s)
time elapsed: 1.1 sec(s)
  • Related