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')