云计算-N体模拟

C代码

这是N体模拟MPI使用的代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <mpi.h>

#define N 256
typedef struct ball
{
	double px, py;//位置
	double vx, vy;//速度
	double ax, ay;//加速度
}ball;

//const int N = 256;
ball ball_list[N];
const double GM = 6.67E-7;//G*M的值其中G为6.67E-11 M为10E4kg
double delta_t = 0.01;//每次计算的时间间隔,越小计算越精确
double r = 0.01;//球的半径
int cycle_times = 400;//周期数
int size;//正方形大小
int *boundary;//每个进程处理数据的位置
FILE* fp;
int i, j;
const char* savefile = "savefile.txt";

void compute_force(int index)//根据作用力计算加速度
{
	int i;
	ball_list[index].ax = 0;//每一时刻情况
	ball_list[index].ay = 0;
	for (i = 0; i < N; i++)
	{
		if (i != index)
		{
			double dx = ball_list[i].px - ball_list[index].px;
			double dy = ball_list[i].py - ball_list[index].py;
			double d = sqrt(dx * dx + dy * dy);
			if (d < 2 * r)
				d = 2 * r;//最小距离是球的直径
			//万有引力加速度:a = GM/r^2
			ball_list[index].ax += GM * (dx) / pow(d, 3);//计算在两坐标的分力
			ball_list[index].ay += GM * (dy) / pow(d, 3);
		}

	}
}
void compute_velocities(int index)
{

	ball_list[index].vx += ball_list[index].ax * delta_t;
	ball_list[index].vy += ball_list[index].ay * delta_t;
}
void compute_positions(int index)
{
	ball_list[index].px += ball_list[index].vx * delta_t;
	//两个条件语句是防止越界
	if (ball_list[index].px > ((size - 1) / 100.0))ball_list[index].px = (size - 1) / 100.0;
	if (ball_list[index].px < 0)ball_list[index].px = 0;
	ball_list[index].py += ball_list[index].vy * delta_t;
	if (ball_list[index].py > ((size - 1) / 100.0))ball_list[index].py = (size - 1) / 100.0;
	if (ball_list[index].py < 0)ball_list[index].py = 0;
}

void save()//保存每个点所在位置
{
	int i;
	fp = fopen(savefile, "w");
	for (i = 0; i < N; i++)
		fprintf(fp, "%lf %lf %lf %lf\n", ball_list[i].px, ball_list[i].py, ball_list[i].vx,ball_list[i].vy);
	fclose(fp);
}

void load()//读取每个点所在位置
{
	int i;
	fp = fopen(savefile, "r");
	for (i = 0; i < N; i++)
		fscanf(fp, "%lf %lf %lf %lf", &ball_list[i].px, &ball_list[i].py, &ball_list[i].vx, &ball_list[i].vy);
	fclose(fp);
}

int main(int argc, char* argv[])
{
	int myid, numprocs;
	clock_t starttime, endtime;
	starttime = clock();
	size = sqrt(N);
	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &myid);
	MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
	MPI_Status status;
	boundary = (int*)malloc(sizeof(int)*(numprocs + 1));//要标明起止线,所以需要+1
	
	//初始化boundary数组
	boundary[0] = 0;
	int tmp = N / numprocs;//整除情况下
	for (i = 1; i <= numprocs; ++i)
	{
		boundary[i] = boundary[i-1] + tmp;//比如前64和元素对应0-63地址,64不取因为后面判断是<
		if(N%numprocs!=0&&i<= N % numprocs)
				boundary[i] += 1;//在不能平分情况下,前几个进程需要多处理一个数据
	}

	//模拟开始
	load();//读取文件
	for (i = 0; i < cycle_times; i++)
	{
		for (j = 0; j < numprocs; j++)
			if (j != myid)
				MPI_Sendrecv((ball_list + boundary[myid]), sizeof(ball) * (boundary[myid + 1] - boundary[myid]),
					MPI_BYTE, j, i * 10 + myid,
					(ball_list + boundary[j]), sizeof(ball) * (boundary[j + 1] - boundary[j]),
					MPI_BYTE, j, i * 10 + j, 
					MPI_COMM_WORLD, &status);
		//更新速度和位置
		for(j = boundary[myid]; j < boundary[myid + 1]; j++) {
			compute_force(j);
			compute_velocities(j);
			compute_positions(j);
		}
		//位置的更新会影响下一个循环的加速度的计算,所以要同步
		MPI_Barrier(MPI_COMM_WORLD);

	}
	
	if (myid == 0) {
		save();//保存结果
		endtime = clock();
		printf("time:%lf\n", (double)(endtime - starttime) / CLOCKS_PER_SEC);
	}
	MPI_Finalize();
}

UI

这是前端界面使用的代码

import time

import tkinter as tk

from tkinter import messagebox



import paramiko

from PIL import Image,ImageTk

import tkinter.font as tkFont

from tkinter import FLAT,GROOVE

import numpy as np

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

from matplotlib.figure import Figure

from tkinter import ttk

from tkinter import StringVar

from NbodyCluster import NbodyCluster







class Window():

    def __init__(self,innerCycle = 400,round = 5):

        self.Nbody=NbodyCluster(innerCycle,round)

        self.font = 'song ti'

        self.createMainFrame()





    def createMainFrame(self):

        root = tk.Tk()

        root.geometry("800x600")

        root.title("N体模拟系统")  # 窗体标题



        screenwidth = root.winfo_screenwidth()

        screenheight = root.winfo_screenheight()

        width, height = self.get_window_size(root)[:2]

        size = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 3)

        root.geometry(size)  # 将窗体移动到屏幕中央



        frame_main = tk.Frame(root)

        frame_main.propagate(False)

        frame_main.pack(expand=tk.YES, fill=tk.BOTH)

        frame_maintop = tk.Frame(frame_main, bg="white", height=120)

        frame_maintop.pack(fill=tk.X, padx=20)



        imagetop = tk.Label(frame_maintop, width=240, height=160)

        imgmaintop = Image.open(r'image/docker.png')

        w, h = imgmaintop.size

        width = 240

        height = 160

        img2 = imgmaintop.resize((width, height), Image.ANTIALIAS)

        _2img = ImageTk.PhotoImage(img2)

        imagetop.image = _2img

        imagetop.config(image=_2img)

        imagetop.pack(side=tk.LEFT, padx=10, pady=10)

        tk.Label(frame_maintop, text="基于docker的n体模拟实验系统", bg="white", fg='black', height=4,

                 font=tkFont.Font(family=self.font, size=20)).pack(side=tk.LEFT)



        root_canvas = tk.Canvas(root, width=800, height=420)

        img_root = self.get_image('./image/qq.png', 1500, 800)

        root_canvas.create_image(500, 300, image=img_root)

        root_canvas.pack()



        img_button = self.get_image('./image/button.png', 220, 80)



        btn01 = tk.Button(root, image=img_button, compound=tk.CENTER, text="创建服务", font=(self.font, 20), relief=FLAT,

                          command=lambda: self.create_service())

        btn02 = tk.Button(root, image=img_button, compound=tk.CENTER, text="查看服务", font=(self.font, 20), relief=FLAT,

                          command=lambda: self.check_service())

        btn03 = tk.Button(root, image=img_button, compound=tk.CENTER, text="删除服务", font=(self.font, 20), relief=FLAT,

                          command=lambda: self.delete_service())

        btn04 = tk.Button(root, image=img_button, compound=tk.CENTER, text="查看docker集群", font=(self.font, 20), relief=FLAT,

                          command=lambda: self.check_docker_swarm())

        btn05 = tk.Button(root, image=img_button, compound=tk.CENTER, text="mpi集群部署", font=(self.font, 20), relief=FLAT,

                          command=lambda: self.mpi_deploy())

        btn06 = tk.Button(root, image=img_button, compound=tk.CENTER, text="mpi n体模拟", font=(self.font, 20), relief=FLAT,

                          command=lambda: self.mpi_Nbody_simulation())

        # 第四步  确定控件放置位置,并设置单击事件

        btn01.place(x=100, y=200, width=220, height=80)

        btn02.place(x=500, y=200, width=220, height=80)

        btn03.place(x=100, y=330, width=220, height=80)

        btn04.place(x=500, y=330, width=220, height=80)

        btn05.place(x=100, y=460, width=220, height=80)

        btn06.place(x=500, y=460, width=220, height=80)



        root.mainloop()





    def get_image(self,filename,width,height):

        img=Image.open(filename).resize((width,height))

        return ImageTk.PhotoImage(img)





    def get_window_size(self,win, update=True):

        """ 获得窗体的尺寸 """

        if update:

            win.update()

        return win.winfo_width(), win.winfo_height(), win.winfo_x(), win.winfo_y()



    # 第1个按钮绑定函数-创建服务

    def create_service(self):

        window1 = tk.Toplevel()

        window1.title("创建服务")

        window1.geometry("400x280")  # 窗体尺寸

        screenwidth1 = window1.winfo_screenwidth()

        screenheight1 = window1.winfo_screenheight()

        width1, height1 = self.get_window_size(window1)[:2]

        size1 = '%dx%d+%d+%d' % (width1, height1, (screenwidth1 - width1) / 2, (screenheight1 - height1) / 3)

        window1.geometry(size1)  # 将窗体移动到屏幕中央



        frame1 = tk.Frame(window1, bg="white")

        frame1.pack(fill=tk.X)

        tk.Label(frame1, text="image:    ", bg="white", fg='black', height=3,

                 font=tkFont.Font(family=self.font, size=15)).pack(side=tk.LEFT, padx=20, pady=10)

        image_entry = tk.Entry(frame1, width=27)

        image_entry.insert(0, "dispel4py/docker.openmpi")

        image_entry.pack(side=tk.LEFT)



        frame2 = tk.Frame(window1, bg="white")

        frame2.pack(fill=tk.X)

        tk.Label(frame2, text="command:  ", bg="white", fg='black', height=3,

                 font=tkFont.Font(family=self.font, size=15)).pack(side=tk.LEFT, padx=20, pady=10)

        command_entry = tk.Entry(frame2, width=27)

        command_entry.insert(0, "Default:None")

        command_entry.pack(side=tk.LEFT)



        frame3 = tk.Frame(window1, bg="white")

        frame3.pack(fill=tk.X)

        tk.Label(frame3, text="name:     ", bg="white", fg='black', height=3,

                 font=tkFont.Font(family=self.font, size=15)).pack(side=tk.LEFT, padx=20, pady=10)

        service_entry = tk.Entry(frame3, width=27)

        service_entry.insert(0, "Default:None")

        service_entry.pack(side=tk.LEFT)



        def confirmation():

            image=image_entry.get()



            if command_entry.get() == "Default:None":

                command=None

            else:

                command=command_entry.get()



            if service_entry.get() == "Default:None":

                service=None

            else:

                service=service_entry.get()

            try:

                ID=self.Nbody.create_service(image,command,service)

                info = "INFO:\nID:{}\nimage:{}\ncommand:{}\nname:{}".format(ID['ID'],image,command,service)

                tk.messagebox.showinfo('创建成功', info,parent = window1)

            except:

                tk.messagebox.showerror('错误','创建失败',parent = window1)

            image_entry.delete(0, "end")

            service_entry.delete(0, "end")

            command_entry.delete(0, "end")





        frame5 = tk.Frame(window1, bg="white")

        frame5.pack(fill=tk.X )

        tk.Button(frame5, text='确认', width=10, height=1, bg='white', relief=GROOVE,command=confirmation).pack(side=tk.RIGHT, padx=10)



    # 第2个按钮绑定函数-查看服务

    def check_service(self):

        window2 = tk.Toplevel()

        window2.title("查看服务")

        window2.geometry("1000x250")  # 窗体尺寸

        screenwidth1 = window2.winfo_screenwidth()

        screenheight1 = window2.winfo_screenheight()

        width1, height1 = self.get_window_size(window2)[:2]

        size1 = '%dx%d+%d+%d' % (width1, height1, (screenwidth1 - width1) / 2, (screenheight1 - height1) / 3)

        window2.geometry(size1)  # 将窗体移动到屏幕中央



        tmp=self.Nbody.getService()

        service_num=len(tmp)

        tree = ttk.Treeview(window2)  # #创建表格对象

        tree["columns"] = ("ID","Name", "Replicas", "Image")  # #定义列

        tree.column("ID", width=250, anchor='center')

        tree.column("Name", width=150, anchor='center')  # #设置列

        tree.column("Replicas", width=80, anchor='center')

        tree.column("Image", width=250, anchor='center')

        tree.heading("ID", text="ID", anchor='center')

        tree.heading("Name", text="Name", anchor='center')  # #设置显示的表头名

        tree.heading("Replicas", text="Replicas", anchor='center')

        tree.heading("Image", text="Image", anchor='center')



        values = []

        for i in range(service_num):

            temp = []

            for key, value in tmp[i].items():

                temp.append(value)

            values.append(temp)

        for i in range(service_num):

            tree.insert("", i, text="service" + str(i + 1), values=values[i])  # #给第0行添加数据,索引值可重复

        tree.pack()





    # 第3个按钮绑定函数-删除服务

    def delete_service(self):

        window3 = tk.Toplevel()

        window3.title("删除服务")

        window3.geometry("900x300")  # 窗体尺寸

        screenwidth1 = window3.winfo_screenwidth()

        screenheight1 = window3.winfo_screenheight()

        width1, height1 = self.get_window_size(window3)[:2]

        size1 = '%dx%d+%d+%d' % (width1, height1, (screenwidth1 - width1) / 2, (screenheight1 - height1) / 3)

        window3.geometry(size1)  # 将窗体移动到屏幕中央



        frame1 = tk.Frame(window3, bg="white")

        frame1.pack(fill=tk.X)

        tk.Label(frame1, text="name/ID:", bg="white", fg='black', height=3,width = 20,

                 font=tkFont.Font(family=self.font, size=10)).pack(side=tk.LEFT, padx=20)

        name_entry = tk.Entry(frame1, width=27)

        name_entry.pack(side=tk.LEFT)







        def confirmation():

            name_Id=name_entry.get()

            try:

                self.Nbody.rmService(name_Id)

                tk.messagebox.showinfo('提示', '成功删除name为{}的服务'.format(name_entry.get()),parent = window3)

            except:

                tk.messagebox.showerror('错误', '删除服务失败',parent = window3)

            name_entry.delete(0, "end")





        frame2 = tk.Frame(window3, bg="white")

        frame2.pack(fill=tk.X)

        tk.Button(frame2, text='确认', width=10, height=1, bg='white', relief=GROOVE, command=confirmation).pack(anchor=tk.E,ipadx = 30,ipady=0)

        tmp = self.Nbody.getService()

        service_num = len(tmp)

        tree = ttk.Treeview(window3)  # #创建表格对象

        tree["columns"] = ("ID", "Name", "Replicas", "Image")  # #定义列

        tree.column("ID", width=250, anchor='center')

        tree.column("Name", width=150, anchor='center')  # #设置列

        tree.column("Replicas", width=80, anchor='center')

        tree.column("Image", width=250, anchor='center')

        tree.heading("ID", text="ID", anchor='center')

        tree.heading("Name", text="Name", anchor='center')  # #设置显示的表头名

        tree.heading("Replicas", text="Replicas", anchor='center')

        tree.heading("Image", text="Image", anchor='center')



        values = []

        for i in range(service_num):

            temp = []

            for key, value in tmp[i].items():

                temp.append(value)

            values.append(temp)

        for i in range(service_num):

            tree.insert("", i, text="service" + str(i + 1), values=values[i])  # #给第0行添加数据,索引值可重复

        tree.pack()







    # 第4个按钮绑定函数-查看docker集群

    def check_docker_swarm(self):

        window4 = tk.Toplevel()

        window4.title("查看docker集群")

        window4.geometry("600x200")  # 窗体尺寸

        screenwidth1 = window4.winfo_screenwidth()

        screenheight1 = window4.winfo_screenheight()

        width1, height1 = self.get_window_size(window4)[:2]

        size1 = '%dx%d+%d+%d' % (width1, height1, (screenwidth1 - width1) / 2, (screenheight1 - height1) / 3)

        window4.geometry(size1)  # 将窗体移动到屏幕中央



        tmp = self.Nbody.getNodeinfo()

        node_num = len(tmp)



        tree = ttk.Treeview(window4)  # #创建表格对象

        tree["columns"] = ("Hostname", "State", "Role", "IP")  # #定义列

        tree.column("Hostname", width=80, anchor='center')  # #设置列

        tree.column("State", width=80, anchor='center')

        tree.column("Role", width=80, anchor='center')

        tree.column("IP", width=160, anchor='center')

        tree.heading("Hostname", text="Hostname", anchor='center')  # #设置显示的表头名

        tree.heading("State", text="State", anchor='center')

        tree.heading("Role", text="Role", anchor='center')

        tree.heading("IP", text="IP", anchor='center')



        values=[]

        for i in range(node_num):

            temp=[]

            for key,value in tmp[i].items():

                temp.append(value)

            values.append(temp)

        for i in range(node_num):

            tree.insert("", i,text="host"+str(i+1), values=values[i])  # #给第0行添加数据,索引值可重复

        tree.pack()



    # 第5个按钮绑定函数-mpi集群部署

    def mpi_deploy(self):

        window5 = tk.Toplevel()

        window5.title("mpi集群部署")

        window5.geometry("400x115")  # 窗体尺寸

        screenwidth1 = window5.winfo_screenwidth()

        screenheight1 = window5.winfo_screenheight()

        width1, height1 = self.get_window_size(window5)[:2]

        size1 = '%dx%d+%d+%d' % (width1, height1, (screenwidth1 - width1) / 2, (screenheight1 - height1) / 3)

        window5.geometry(size1)  # 将窗体移动到屏幕中央



        frame1 = tk.Frame(window5, bg="white")

        frame1.pack(fill=tk.X)

        tk.Label(frame1, text="node_num:          ", bg="white", fg='black', height=3,

                 font=tkFont.Font(family=self.font, size=10)).pack(side=tk.LEFT, padx=20, pady=10)

        num_entry = tk.Entry(frame1, width=27)

        num_entry.pack(side=tk.LEFT)



        def confirmation():

            try:

                num = int(num_entry.get())

                self.Nbody.deployMpi(num)

                tk.messagebox.showinfo('提示', '成功部署{}个节点的mpi集群'.format(num),parent = window5)

            except:

                tk.messagebox.showerror('错误', '部署集群失败',parent = window5)

            num_entry.delete(0, "end")





        frame2 = tk.Frame(window5, bg="white")

        frame2.pack(fill=tk.X)

        tk.Button(frame2, text='确认', width=10, height=1, bg='white', relief=GROOVE, command=confirmation).pack(

            side=tk.RIGHT, padx=10)



    # 第6个按钮绑定函数-mpi n体模拟

    def mpi_Nbody_simulation(self):

        window6 = tk.Toplevel()

        window6.title("mpi n体模拟")

        window6.geometry("600x610")  # 窗体尺寸

        screenwidth1 = window6.winfo_screenwidth()

        screenheight1 = window6.winfo_screenheight()

        width1, height1 = self.get_window_size(window6)[:2]

        size1 = '%dx%d+%d+%d' % (width1, height1, (screenwidth1 - width1) / 2, (screenheight1 - height1) / 3)

        window6.geometry(size1)  # 将窗体移动到屏幕中央



        figure = Figure()

        canvas = FigureCanvasTkAgg(figure, window6)

        canvas.draw()  # 注意show方法已经过时了,这里改用draw

        canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=tk.YES)  # 随窗口大小调整而调整



        var = StringVar()

        var.set("开始")

        canvas1 = tk.Canvas(window6, width=590, height=26, bg="white")

        canvas1.pack(ipadx=5)





        def confirmation():

            self.Nbody.initialLocation()

            self.Nbody.plot(figure, canvas,canvas1,var)

            status = self.Nbody.subRun(figure, canvas,canvas1,var)

            if status != self.Nbody.round - 1:

                tk.messagebox.showerror('error', "异常处理中.....",parent=window6)

                while status != self.Nbody.round - 1:

                    self.Nbody.deployMpi()

                    time.sleep(10)

                    for service in self.Nbody.client.services():

                        if 'head' in service['Spec']['Name']:

                            port = service['Endpoint']['Ports'][0]['PublishedPort']

                    ssh = paramiko.SSHClient()  # 创建一个ssh的客户端,用来连接服务器

                    know_host = paramiko.AutoAddPolicy()  # 创建一个ssh的白名单

                    ssh.set_missing_host_key_policy(know_host)  # 加载创建的白名单

                    while True:

                        try:

                            ssh.connect(hostname="localhost", port=port, username="root", password="tutorial")

                            break

                        except:

                            print("异常处理:尝试连接主节点@" + str(port))

                            time.sleep(5)

                    tk.messagebox.showinfo('info', "异常处理完毕!",parent=window6)

                    print("continue...")

                    status = self.Nbody.subRun(figure, canvas,canvas1,var,status)

            tk.messagebox.showinfo('提示', "执行完毕",parent=window6)



        tk.Button(window6, textvariable=var, width=10, height=5, bg='white', relief=GROOVE, command=confirmation).pack()

        window6.mainloop()









if __name__ == '__main__':

    Window=Window()

   

详细设计

这是python和docker交互的代码

import time
import docker
import paramiko
import yaml
import numpy as np
import os


class NbodyCluster():
    def __init__(self,innerCycle = 400,round = 5):
        self.client = docker.APIClient(base_url='unix://var/run/docker.sock',version='auto',timeout=5) # connect the cluster
        self.NodeFilepath = "/home/share/savefile.txt"
        self.innerCycle = innerCycle
        self.round = round


    def initialLocation(self,N=256):
        """
       :param N: 实现保存文件的初始化
       """
        size = N ** 0.5
        px = [0.01 * (i % size) for i in range(N)]
        py = [0.01 * (i // size) for i in range(N)]
        vx = [0 for i in range(N)]
        vy = [0 for i in range(N)]
        # 写出到本地
        with open(self.NodeFilepath, 'w') as fp:
            for i in range(N):
                fp.writelines("{:.4f} {:.4f} {:.4f} {:.4f}\n".format(px[i], py[i], vx[i], vy[i]))

    def getNodeinfo(self):
        '''get node info '''
        node1 = self.client.nodes()[0]
        node2 = self.client.nodes()[1]
        info1 = {}
        info2 = {}
        info1['Hostname'] = node1['Description']['Hostname']
        info1['State'] = node1['Status']['State']
        info1['Role'] = node1['Spec']['Role']
        info1['IP'] = node1['Status']['Addr']

        info2['Hostname'] = node2['Description']['Hostname']
        info2['State'] = node2['Status']['State']
        info2['Role'] = node2['Spec']['Role']
        info2['IP'] = node2['Status']['Addr']
        return [info1,info2]

    def isActive(self):
        """
        check worker is active
        :return:
        """
        nodes = self.client.nodes()
        for node in nodes:
            if node['Description']['Hostname']=='slave':
                if node['Status']['State']=='ready':
                    return True
                else:
                    return False


    def create_service(self,image = 'dispel4py/docker.openmpi',command = None,name = None):
        container_spec = docker.types.ContainerSpec(image=image,command=command)
        task_tmpl = docker.types.TaskTemplate(container_spec)
        service_id = self.client.create_service(task_tmpl, name=name)
        return service_id

    def getService(self):
        services = self.client.services()
        result = []
        for service in services:
            tmp = {}
            tmp['ID'] = service['ID']
            tmp['name'] = service['Spec']['Name']
            tmp['Replicas'] = service['Spec']['Mode']['Replicated']['Replicas']
            tmp['image'] = service['Spec']['TaskTemplate']['ContainerSpec']['Image'].split('@')[0]
            result.append(tmp)
        return result

    def rmService(self,name):
        self.client.remove_service(name)


    def deployMpi(self,node_num=4):
        with open('/home/docker-compose.yml') as fp:
            yaml_obj = yaml.load(fp.read())
            yaml_obj['services']['mpi_node']['deploy']['replicas'] = node_num
            main_yaml = open('/home/docker-compose.yml', 'w')
            yaml.dump(yaml_obj, main_yaml)
            main_yaml.close()
        os.system('docker stack deploy --compose-file /home/docker-compose.yml mpi')
        time.sleep(30)


    def plot(self,figure,canvas,canvas1,var,iteration = 0):
        x, y,_0,_1 = np.loadtxt(self.NodeFilepath, delimiter=' ', unpack=True)
        figure.clf()
        sub = figure.add_subplot(111)
        sub.plot(x, y, '*', color='black')
        sub.set_title("iteration:{}/{}".format(iteration, self.innerCycle * self.round))

        if iteration==0:
            fill_line = canvas1.create_rectangle(2, 2, 0, 27, width=0, fill="white")
            canvas1.coords(fill_line, (0, 0, 600, 30))
        else:
            fill_line = canvas1.create_rectangle(2, 2, 0, 27, width=0, fill="green")
            canvas1.coords(fill_line, (0, 0, 1.5*iteration/5, 30))
        if (iteration/20) >= 100:
            var.set("迭代进度:" + "100%")
        else:
            var.set("迭代进度:" + str(iteration/20) + "%")
        canvas.draw()

    def subRun(self,figure,canvas,canvas1,var,currentIteration = 0):
        for service in self.client.services():
            if 'head' in service['Spec']['Name']:
                port = service['Endpoint']['Ports'][0]['PublishedPort']
        ssh = paramiko.SSHClient() # 创建一个ssh的客户端,用来连接服务器
        know_host = paramiko.AutoAddPolicy() # 创建一个ssh的白名单
        ssh.set_missing_host_key_policy(know_host)# 加载创建的白名单

        # 获取运行结点的ip并保存到文件
        while True:
            try:
                ssh.connect(hostname="localhost",port=port,username="root",password="tutorial")
                if(currentIteration !=0):
                    print("异常处理完毕")
                break
            except:
                print("异常处理:尝试连接主节点@"+str(port))
                time.sleep(5)

        chanelSSHOb = ssh.invoke_shell()
        time.sleep(0.1)
        chanelSSHOb.send('su tutorial\n')
        time.sleep(0.1)
        chanelSSHOb.send('cd ~\n')
        time.sleep(0.1)
        chanelSSHOb.send("dig tasks.mpi_node|grep ^tasks|awk '{print $5}' > mpi_config_file && sudo cp mpi_config_file ./works/\n")
        time.sleep(0.1)
        print(chanelSSHOb.recv(9999).decode("utf8"))

        nodeIP=[]#ip of nodes who runs mpi programme
        with open(file='/home/share/mpi_config_file') as fp:
            for line in fp.readlines():
                nodeIP.append(line.split()[0])
        lastModifiedTime = os.stat(self.NodeFilepath).st_mtime
        try:
            chanelSSHOb.send("ssh " + nodeIP[0] + '\n')
            time.sleep(0.1)
        except:
            pass
        chanelSSHOb.send("cd ~/works\n")
        time.sleep(0.1)
        chanelSSHOb.send("mpicc ./nbody.c -o ./nbody -lm\n")
        time.sleep(0.3)
        print(chanelSSHOb.recv(9999).decode("utf8"))
        for i in range(currentIteration,self.round):
            chanelSSHOb.send("mpiexec --mca btl_tcp_if_include eth0 -np "+str(len(nodeIP))+ " -hostfile ./mpi_config_file ./nbody\n") # execute mpi programme
            for j in range(100):
                modifiedTime = os.stat(self.NodeFilepath).st_mtime
                if modifiedTime!= lastModifiedTime:
                    lastModifiedTime = modifiedTime
                    break
                if currentIteration==0 and (not self.isActive()):
                        print('\033[31m断开连接\033[0m')
                        return i
                else:
                    if currentIteration==0:
                        time.sleep(5)
                    else:
                        time.sleep(1)
                    print("\033[32m保持连接\033[0m")

            print(chanelSSHOb.recv(999999).decode("utf8"))
            self.plot(figure,canvas,canvas1,var,(i+1)*400)
        return i


if __name__ == "__main__":
    nbody = NbodyCluster()
    nbody.rmService('mpi_mpi_head')
    nbody.rmService('mpi_mpi_node')


  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值