简体   繁体   中英

Python3 multiprocessing a 'for' loop

I really want to ask this, because even if I read the documentation and have seen some examples cannot really get the point of how to use this.

I have a Raspberry pi 3 model B, and I cross compiled QT 5.6 and the lastest SIP and PyQt5 versions to develop Python GUIs and use the linux frame buffer, everything was a success, until I ran this part of my code

def refresh_data(self):
        if self.setTarget == 1:
            for x in range(0, self.targetnum):
                self.target.append(getShadowInfo(x))
                if float(self.target[x]) != self.datalist[x]:
                    if float(self.target[x]) > self.datalist[x]:
                        self.step.append(float(self.target[x]) - self.datalist[x])
                        self.negative.append(0)
                    else:
                        self.step.append(self.datalist[x] - float(self.target[x]))
                        self.negative.append(1)
                else:
                    self.step.append(0)
                    self.negative.append(0)
                self.step[x] *= 0.1
            self.setTarget = 0
            self.setTodaysDate(self.year, self.month, self.day, self.hour, self.min)
        self.stopv += 10
        for x in range(0, self.targetnum):
            if self.step[x] != 0:
                if self.negative[x] == 0:
                    self.datalist[x] += self.step[x]
                else:
                    self.datalist[x] -= self.step[x]
                self.setCustomParameter(x)
        if all(i == 0 for i in self.step):
            self.timer.stop()
        if self.stopv >= 100:
            self.timer.stop()

Which reads data from an external file and set it as a target, then it increase or decrease the actual value to update it on the python GUI, that way it looks smooth, but meanwhile that happens, the performance gets poor and it even execute the code slowly than it should (is ran by an 50ms Qtimer). With htop, I notice that when running this part of the code, my RPi only use one core of its four, can somebody help me to to multiprocess the two for loops?, or maybe better, the refresh_data function?.

EDIT!

setCustomParameter function

def setCustomParameter(self, intparameter):
        if intparameter == 1:
            #RPMMeter
            self.hygrometer.setProperty("gaugeValue", round(self.datalist[1], 2))
            self.label_5.setText(QCoreApplication.translate("MainWindow", "Engine Speed: " +
            str(round(self.datalist[1], 2)) + " RPM"))
        if intparameter == 2:
            #Pressure
            self.label.setText(QCoreApplication.translate("MainWindow",
            str(round(self.datalist[2], 2)) + " KPa"))
            self.progressBar.setProperty("value", self.datalist[2])
        if intparameter == 3:
            self.thermometer.setProperty("thermoValue", round(self.datalist[3], 2))
        if intparameter == 4:
            self.KW_Meter.setProperty("gaugeValue", round(self.datalist[4], 2))
        if intparameter == 5:
            self.Battery_bank_label.setText(QCoreApplication.translate("MainWindow",
            "Battery Bank Voltage: " + str(round(self.datalist[5], 2)) + "V (MEDIUM)"))

it looks like you might be able to 3x the speed by reducing (two for loops, 1 all which is also a for loop) to 1 for loop with some clever placement of the if statements.

by zipping the target, datalist. assuming that self.target, self.negative, self.datalist, and self.step are all the same length.

for i, (t, d) in enumerate(zip(self.target, self.datalist)):
    t = float(t)
    if (t != d) and (t > d) and (self.setTarget == 1):
        self.target.append(getShadowInfo(x))
        self.datalist = d + (t - d) * .1
    elif (t != d) and (t <= d) and (self.setTarget == 1):
        self.target.append(getShadowInfo(x))
        self.datalist = d - (d - t) * .1
    else:
        self.setCustomParameter(i)

if self.setTarget == 1
    self.setTarget = 0
    self.setTodaysDate(self.year, self.month, self.day, self.hour, self.min)

if you were able to figure out how to reduce to 1 for loop, you could then multiprocess it by replacing the for loop entirely by returning the index and data from a multiprocessing.pool.Pool :

# replacing ... self.datalist = d - (d - t) * .1
# with ... return i, d - (d - t) * .1
results = mp.Pool(4).starmap(return_data, zip(self.target, self.datalist))
for i, d in results:
    self.datalist[i] = d

note: the trick is going to be figuring out how to process what needs updating without mutating self.target in the for loop

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