èªåè»ãããããå·¥åŠãéèãªã©ã®æ¥çã§ã¯ã補åãæ¹åããããã«ãã·ãã¥ã¬ãŒã·ã§ã³ãæ©æ¢°åŠç¿ (ML) ã¢ãã«ã®ãã¬ãŒãã³ã°ãããã°ããŒã¿åæãªã©ã®èšç®ã¯ãŒã¯ããŒãã®å®è£
ãå¢å ã®äžéããã©ã£ãŠããŸããäŸãã°ãèªåè»ã¡ãŒã«ãŒã¯ã·ãã¥ã¬ãŒã·ã§ã³ã«äŸæ ããŠèªåé転æ©èœããã¹ãããããããå·¥åŠåéã®äŒæ¥ã¯ ML ã¢ã«ãŽãªãºã ããã¬ãŒãã³ã°ããŠããããã®èªèæ©èœã匷åããŠããã»ããéèæ¥çã®äŒæ¥ã¯è©³çްãªåæãå®è¡ããŠããªã¹ã¯ç®¡çãååŒåŠçãäžæ£è¡çºã®æ€åºãæ¹åããŠããŸãã ã·ãã¥ã¬ãŒã·ã§ã³ãå«ããããã®ã¯ãŒã¯ããŒãã®äžéšã¯ãã³ã³ããŒãã³ãã®å€æ§æ§ãšå³ããèšç®èŠä»¶ã«ãããå®è¡ãç¹ã«è€éã§ããäŸãã°ãé転ã·ãã¥ã¬ãŒã·ã§ã³ã«ã¯ã3D ä»®æ³ç°å¢ãè»äž¡ã»ã³ãµãŒããŒã¿ãè»äž¡ã®æåãå¶åŸ¡ããè»äž¡ãã€ããã¯ã¹ãªã©ã®çæã䌎ããŸããããããå·¥åŠã·ãã¥ã¬ãŒã·ã§ã³ã§ã¯ãå€§èŠæš¡ãªå庫ç°å¢ã§ãçžäºã«ãããã³ä»ã®ã·ã¹ãã ãšã€ã³ã¿ã©ã¯ã·ã§ã³ããäœçŸãã®èªåŸåé
éããããããã¹ãããå¯èœæ§ããããŸãã AWS Batch ã¯ã Amazon Elastic Container Service (Amazon ECS) ã Amazon Elastic Kubernetes Service (Amazon EKS) ã AWS Fargate ãããã³ Amazon EC2 ã¹ããã ãŸã㯠ãªã³ããã³ã ã€ã³ã¹ã¿ã³ã¹ãªã©ãããŸããŸãª AWS ã³ã³ãã¥ãŒãã£ã³ã°ãµãŒãã¹ã«ããã£ãŠãããã¯ãŒã¯ããŒããå®è¡ããã®ã«åœ¹ç«ã€ãã«ãããŒãžããµãŒãã¹ã§ããåŸæ¥ãAWS Batch ã§ã¯åäžã³ã³ããã®ãžã§ãã®ã¿ãèš±å¯ãããŠããããã¹ãŠã®ã³ã³ããŒãã³ããã¢ããªã·ãã¯ã³ã³ããã«ããŒãžããã«ã¯è¿œå ã®ã¹ããããå¿
èŠã§ããããŸããããŒã¿ãã°èšé²ãªã©ã®è¿œå ãµãŒãã¹ãæäŸããããšã§ã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³ãè£å®ããè£å©ã³ã³ããã§ãããå¥åã®ããµã€ãã«ãŒãã³ã³ããã䜿çšã§ããŸããã§ãããã³ãŒãã®å€æŽã¯ã³ã³ããå
šäœã®åæ§ç¯ãæå³ããããããã®è¿œå ã®äœæ¥ã«ã¯ããœãããŠã§ã¢éçºãIT éçšãå質ä¿èšŒ (QA) ãªã©ã®è€æ°ã®ããŒã ã«ããã調æŽãå¿
èŠã§ããã AWS Batch ã¯ãã«ãã³ã³ãããžã§ããæäŸããããã«ãªããŸãããããã«ãããèªåé転è»ãããããå·¥åŠãªã©ã®åéã§å€§èŠæš¡ãªã·ãã¥ã¬ãŒã·ã§ã³ãããç°¡åãã€è¿
éã«å®è¡ã§ããŸãããããã®ã¯ãŒã¯ããŒãã¯éåžžãã·ãã¥ã¬ãŒã·ã§ã³èªäœãšãã·ãã¥ã¬ãŒã·ã§ã³ãšã€ã³ã¿ã©ã¯ã·ã§ã³ãããã¹ã察象ã®ã·ã¹ãã (ãšãŒãžã§ã³ããšãåŒã°ããŸã) ã«åå²ãããŸãããããã® 2 ã€ã®ã³ã³ããŒãã³ãã¯ãå€ãã®å Žåãç°ãªãããŒã ã«ãã£ãŠéçºããã³æé©åãããŸãããžã§ãããšã«è€æ°ã®ã³ã³ãããå®è¡ã§ãããããAWS Batch ãæäŸããé«åºŠãªã¹ã±ãŒãªã³ã°ãã¹ã±ãžã¥ãŒãªã³ã°ãã³ã¹ãã®æé©åãå©çšã§ããã»ãã3D ç°å¢ãããããã»ã³ãµãŒãã¢ãã¿ãªã³ã°ãµã€ãã«ãŒãªã©ã®ããŸããŸãªã³ã³ããŒãã³ãã衚ãã¢ãžã¥ãŒã«åŒã³ã³ããã䜿çšã§ããŸããå®éã IPG Automotive ã MORAI ã Robotec.ai ãªã©ã®ã客æ§ã¯æ¢ã« AWS Batch ãã«ãã³ã³ãããžã§ãã䜿çšããŠã¯ã©ãŠãã§ã·ãã¥ã¬ãŒã·ã§ã³ãœãããŠã§ã¢ãå®è¡ããŠããŸãã ç°¡åãªäŸã䜿çšããŠå®éã«ãããã©ã®ããã«æ©èœããããèŠãŠãè¿·è·¯ãè§£ãã®ã楜ããã§ã¿ãŸãããã ã³ã³ããäžã§å®è¡ãããã·ãã¥ã¬ãŒã·ã§ã³ã®æ§ç¯ æ¬çªç°å¢ã§ã¯ãããããæ¢åã®ã·ãã¥ã¬ãŒã·ã§ã³ãœãããŠã§ã¢ã䜿çšããããšã«ãªããŸãããã®èšäºã§ã¯ããšãŒãžã§ã³ã/ã¢ãã«ã·ãã¥ã¬ãŒã·ã§ã³ã®ç°¡æããŒãžã§ã³ãæ§ç¯ããŸãããã³ãŒãã®è©³çްã«èå³ããªãå Žåã¯ããã®ã»ã¯ã·ã§ã³ãé£ã°ããŠãAWS Batch ã®èšå®æ¹æ³ã«ãé²ã¿ãã ããã ãã®ã·ãã¥ã¬ãŒã·ã§ã³ã§ã¯ãæ¢çŽ¢ããäžçã¯ã©ã³ãã ã«çæããã 2D ã®è¿·è·¯ã§ãããšãŒãžã§ã³ãã«ã¯ãè¿·è·¯ãæ¢çŽ¢ããŠéµãèŠã€ããåºå£ã«å°éãããšããã¿ã¹ã¯ã課ãããŠããŸããããæå³ããã㯠3 ã€ã®å Žæãããçµè·¯æ¢çŽ¢åé¡ã®å
žåçãªäŸã§ãã ããã¯ãéå§ ( S )ãçµäº ( E )ãããã³ã㌠( K ) ã®äœçœ®ã瀺ããè¿·è·¯ã®ãµã³ãã«ãããã§ãã ãšãŒãžã§ã³ããšã¢ãã«ã 2 ã€ã®å¥ã
ã®ã³ã³ããã«åé¢ããããšã§ãç°ãªãããŒã ããããããåå¥ã«äœæ¥ã§ããããã«ãªããŸããåããŒã ã¯ãã·ãã¥ã¬ãŒã·ã§ã³ã«è©³çްã远å ãããããšãŒãžã§ã³ããè¿·è·¯ãæ¢çŽ¢ããæ¹æ³ã«ã€ããŠããåªããæŠç¥ãèŠã€ããããããªã©ãèªåã®æ
åœéšåã®æ¹åã«éäžã§ããŸãã è¿·è·¯ã¢ãã«ã®ã³ãŒãã¯æ¬¡ã®ãšããã§ã ( app.py )ãã©ã¡ãã®äŸã§ã Python ã䜿çšããŸããããã®ã¢ãã«ã¯ããšãŒãžã§ã³ããè¿·è·¯å
ãç§»åããããéµãèŠã€ããŠåºå£ã«å°éãããã©ãããææ¡ãããããããã«äœ¿çšã§ãã REST API ãå
¬éããŸããè¿·è·¯ã¢ãã«ã¯ REST API ã« Flask ã䜿çšããŸãã import json import random from flask import Flask, request, Response ready = False # ãããããŒã¿ãè¿·è·¯å
ã«ä¿åããæ¹æ³ # ãµã€ãºæå®ãã (å¹
x é«ã) = (4 x 3) # # 012345678 # 0: +-+-+ +-+ # 1: | | | | # 2: +-+ +-+-+ # 3: | | | | # 4: +-+-+ +-+ # 5: | | | | | # 6: +-+-+-+-+ # 7: æªäœ¿çš class WrongDirection(Exception): pass class Maze: UP, RIGHT, DOWN, LEFT = 0, 1, 2, 3 OPEN, WALL = 0, 1 @staticmethod def distance(p1, p2): (x1, y1) = p1 (x2, y2) = p2 return abs(y2-y1) + abs(x2-x1) @staticmethod def random_dir(): return random.randrange(4) @staticmethod def go_dir(x, y, d): if d == Maze.UP: return (x, y - 1) elif d == Maze.RIGHT: return (x + 1, y) elif d == Maze.DOWN: return (x, y + 1) elif d == Maze.LEFT: return (x - 1, y) else: raise WrongDirection(f"Direction: {d}") def __init__(self, width, height): self.width = width self.height = height self.generate() def area(self): return self.width * self.height def min_lenght(self): return self.area() / 5 def min_distance(self): return (self.width + self.height) / 5 def get_pos_dir(self, x, y, d): if d == Maze.UP: return self.maze[y][2 * x + 1] elif d == Maze.RIGHT: return self.maze[y][2 * x + 2] elif d == Maze.DOWN: return self.maze[y + 1][2 * x + 1] elif d == Maze.LEFT: return self.maze[y][2 * x] else: raise WrongDirection(f"Direction: {d}") def set_pos_dir(self, x, y, d, v): if d == Maze.UP: self.maze[y][2 * x + 1] = v elif d == Maze.RIGHT: self.maze[y][2 * x + 2] = v elif d == Maze.DOWN: self.maze[y + 1][2 * x + 1] = v elif d == Maze.LEFT: self.maze[y][2 * x] = v else: WrongDirection(f"Direction: {d} Value: {v}") def is_inside(self, x, y): return 0 <= y < self.height and 0 <= x < self.width def generate(self): self.maze = [] # ãã¹ãŠã®å¢çãéããŸã for y in range(0, self.height + 1): self.maze.append([Maze.WALL] * (2 * self.width + 1)) # ããããã®å¢çç·ã§ã©ã³ãã ãªéå§ç¹ãååŸããŸã if random.random() < 0.5: sx = random.randrange(self.width) if random.random() < 0.5: sy = 0 self.set_pos_dir(sx, sy, Maze.UP, Maze.OPEN) else: sy = self.height - 1 self.set_pos_dir(sx, sy, Maze.DOWN, Maze.OPEN) else: sy = random.randrange(self.height) if random.random() < 0.5: sx = 0 self.set_pos_dir(sx, sy, Maze.LEFT, Maze.OPEN) else: sx = self.width - 1 self.set_pos_dir(sx, sy, Maze.RIGHT, Maze.OPEN) self.start = (sx, sy) been = [self.start] pos = -1 solved = False generate_status = 0 old_generate_status = 0 while len(been) < self.area(): (x, y) = been[pos] sd = Maze.random_dir() for nd in range(4): d = (sd + nd) % 4 if self.get_pos_dir(x, y, d) != Maze.WALL: continue (nx, ny) = Maze.go_dir(x, y, d) if (nx, ny) in been: continue if self.is_inside(nx, ny): self.set_pos_dir(x, y, d, Maze.OPEN) been.append((nx, ny)) pos = -1 generate_status = len(been) / self.area() if generate_status - old_generate_status > 0.1: old_generate_status = generate_status print(f"{generate_status * 100:.2f}%") break elif solved or len(been) < self.min_lenght(): continue else: self.set_pos_dir(x, y, d, Maze.OPEN) self.end = (x, y) solved = True pos = -1 - random.randrange(len(been)) break else: pos -= 1 if pos < -len(been): pos = -1 self.key = None while(self.key == None): kx = random.randrange(self.width) ky = random.randrange(self.height) if (Maze.distance(self.start, (kx,ky)) > self.min_distance() and Maze.distance(self.end, (kx,ky)) > self.min_distance()): self.key = (kx, ky) def get_label(self, x, y): if (x, y) == self.start: c = 'S' elif (x, y) == self.end: c = 'E' elif (x, y) == self.key: c = 'K' else: c = ' ' return c def map(self, moves=[]): map = '' for py in range(self.height * 2 + 1): row = '' for px in range(self.width * 2 + 1): x = int(px / 2) y = int(py / 2) if py % 2 == 0: # å¶æ°è¡ if px % 2 == 0: c = '+' else: v = self.get_pos_dir(x, y, self.UP) if v == Maze.OPEN: c = ' ' elif v == Maze.WALL: c = '-' else: # 奿°è¡ if px % 2 == 0: v = self.get_pos_dir(x, y, self.LEFT) if v == Maze.OPEN: c = ' ' elif v == Maze.WALL: c = '|' else: c = self.get_label(x, y) if c == ' ' and [x, y] in moves: c = '*' row += c map += row + '\n' return map app = Flask(__name__) @app.route('/') def hello_maze(): return "<p>Hello, Maze!</p>" @app.route('/maze/map', methods=['GET', 'POST']) def maze_map(): if not ready: return Response(status=503, retry_after=10) if request.method == 'GET': return '<pre>' + maze.map() + '</pre>' else: moves = request.get_json() return maze.map(moves) @app.route('/maze/start') def maze_start(): if not ready: return Response(status=503, retry_after=10) start = { 'x': maze.start[0], 'y': maze.start[1] } return json.dumps(start) @app.route('/maze/size') def maze_size(): if not ready: return Response(status=503, retry_after=10) size = { 'width': maze.width, 'height': maze.height } return json.dumps(size) @app.route('/maze/pos/<int:y>/<int:x>') def maze_pos(y, x): if not ready: return Response(status=503, retry_after=10) pos = { 'here': maze.get_label(x, y), 'up': maze.get_pos_dir(x, y, Maze.UP), 'down': maze.get_pos_dir(x, y, Maze.DOWN), 'left': maze.get_pos_dir(x, y, Maze.LEFT), 'right': maze.get_pos_dir(x, y, Maze.RIGHT), } return json.dumps(pos) WIDTH = 80 HEIGHT = 20 maze = Maze(WIDTH, HEIGHT) ready = True è¿·è·¯ã¢ãã« ( requirements.txt å
) ã®å¯äžã®èŠä»¶ã¯ã Flask ã¢ãžã¥ãŒã«ã§ãã è¿·è·¯ã¢ãã«ãå®è¡ããã³ã³ããã€ã¡ãŒãžãäœæããã«ã¯ããã® Dockerfile ã䜿çšããŸãã FROM --platform=linux/amd64 public.ecr.aws/docker/library/python:3.12-alpine WORKDIR /app COPY requirements.txt requirements.txt RUN pip3 install -r requirements.txt COPY . . CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0", "--port=5555"] ãšãŒãžã§ã³ãã®ã³ãŒãã¯æ¬¡ã®ãšããã§ã ( agent.py )ããŸãããšãŒãžã§ã³ãã¯ã¢ãã«ã«è¿·è·¯ã®ãµã€ãºãšéå§äœçœ®ãããããŸãããã®åŸãç¬èªã®æŠç¥ãé©çšããŠè¿·è·¯ãæ¢çŽ¢ãã解決ããŸãããã®å®è£
ã§ã¯ããšãŒãžã§ã³ãã¯ã«ãŒããã©ã³ãã ã«éžæããåããã¹ãè€æ°åãã©ãããšãé¿ããããšããŸãã import random import requests from requests.adapters import HTTPAdapter, Retry HOST = '127.0.0.1' PORT = 5555 BASE_URL = f"http://{HOST}:{PORT}/maze" UP, RIGHT, DOWN, LEFT = 0, 1, 2, 3 OPEN, WALL = 0, 1 s = requests.Session() retries = Retry(total=10, backoff_factor=1) s.mount('http://', HTTPAdapter(max_retries=retries)) r = s.get(f"{BASE_URL}/size") size = r.json() print('SIZE', size) r = s.get(f"{BASE_URL}/start") start = r.json() print('START', start) y = start['y'] x = start['x'] found_key = False been = set((x, y)) moves = [(x, y)] moves_stack = [(x, y)] while True: r = s.get(f"{BASE_URL}/pos/{y}/{x}") pos = r.json() if pos['here'] == 'K' and not found_key: print(f"({x}, {y}) key found") found_key = True been = set((x, y)) moves_stack = [(x, y)] if pos['here'] == 'E' and found_key: print(f"({x}, {y}) exit") break dirs = list(range(4)) random.shuffle(dirs) for d in dirs: nx, ny = x, y if d == UP and pos['up'] == 0: ny -= 1 if d == RIGHT and pos['right'] == 0: nx += 1 if d == DOWN and pos['down'] == 0: ny += 1 if d == LEFT and pos['left'] == 0: nx -= 1 if nx < 0 or nx >= size['width'] or ny < 0 or ny >= size['height']: continue if (nx, ny) in been: continue x, y = nx, ny been.add((x, y)) moves.append((x, y)) moves_stack.append((x, y)) break else: if len(moves_stack) > 0: x, y = moves_stack.pop() else: print("No moves left") break print(f"Solution length: {len(moves)}") print(moves) r = s.post(f'{BASE_URL}/map', json=moves) print(r.text) s.close() ãšãŒãžã§ã³ãã®å¯äžã®äŸåé¢ä¿ ( requirements.txt å
) ã¯ã requests ã¢ãžã¥ãŒã«ã§ãã ããã¯ããšãŒãžã§ã³ãã®ã³ã³ããã€ã¡ãŒãžãäœæããããã«äœ¿çšãã Dockerfile ã§ãã FROM --platform=linux/amd64 public.ecr.aws/docker/library/python:3.12-alpine WORKDIR /app COPY requirements.txt requirements.txt RUN pip3 install -r requirements.txt COPY . . CMD [ "python3", "agent.py"] ãã®ç°¡ç¥åãããããŒãžã§ã³ã®ã·ãã¥ã¬ãŒã·ã§ã³ã¯ããŒã«ã«ã§ç°¡åã«å®è¡ã§ããŸãããã¯ã©ãŠããå©çšãããšãããå€§èŠæš¡ã«å®è¡ã (ããå€§èŠæš¡ã§è©³çްãªè¿·è·¯ã§å®è¡ãããªã©)ãè€æ°ã®ãšãŒãžã§ã³ãããã¹ãããŠäœ¿çšããæé©ãªæŠç¥ãèŠã€ããããšãã§ããŸããçŸå®ã®ã·ããªãªã§ã¯ããšãŒãžã§ã³ãã®æ¹åã¯ãã®åŸãèªåé転è»ãããããæé€æ©ãªã©ã®ç©çããã€ã¹ã«å®è£
ãããŸãã ãã«ãã³ã³ãããžã§ãã䜿çšããã·ãã¥ã¬ãŒã·ã§ã³ã®å®è¡ AWS Batch ãå©çšããŠãžã§ããå®è¡ããã«ã¯ã次㮠3 ã€ã®ãªãœãŒã¹ãèšå®ããå¿
èŠããããŸã: ãžã§ããå®è¡ãã ã³ã³ãã¥ãŒãã£ã³ã°ç°å¢ ãžã§ããéä¿¡ãã ãžã§ããã¥ãŒ 䜿çšããã³ã³ããã€ã¡ãŒãžãªã©ããžã§ãã®å®è¡æ¹æ³ãèšè¿°ãã ãžã§ãå®çŸ© AWS Batch ã³ã³ãœãŒã« ã§ãããã²ãŒã·ã§ã³ãã€ã³ãã [ã³ã³ãã¥ãŒãã£ã³ã°ç°å¢] ãéžæããæ¬¡ã« [äœæ] ãéžæããŸããçŸåšãFargateãAmazon EC2ããŸã㯠Amazon EKS ãå©çšããéžæè¢ããããŸããFargate ãå©çšãããšããžã§ãå®çŸ©ã§æå®ãããªãœãŒã¹èŠä»¶ã«å³å¯ã«äžèŽãããããšãã§ããŸãããã ããã·ãã¥ã¬ãŒã·ã§ã³ã§ã¯éåžžã倧éã§ã¯ãããã®ã®éçãªéã®ãªãœãŒã¹ã«ã¢ã¯ã»ã¹ããå¿
èŠããããèšç®ãé«éåããããã« GPU ã䜿çšãããŸãããã®ãããããã§ã¯ [Amazon EC2] ãéžæããŸãã AWS Batch ã EC2 ã€ã³ã¹ã¿ã³ã¹ãã¹ã±ãŒã«ããã³èšå®ã§ããããã«ã [ãããŒãžã] ãªãŒã±ã¹ãã¬ãŒã·ã§ã³ã¿ã€ããéžæããŸãããã®åŸãã³ã³ãã¥ãŒãã£ã³ã°ç°å¢ã®ååãå
¥åãããµãŒãã¹ã«ãªã³ã¯ãããããŒã« (AWS Batch ã以åã«äœæãããã®) ãšã(EC2 ã€ã³ã¹ã¿ã³ã¹äžã§å®è¡ãããŠãã) ECS ã³ã³ãããšãŒãžã§ã³ããç§ã«ä»£ãã£ãŠ AWS API ã«å¯ŸããŠåŒã³åºããå®è¡ããããã«äœ¿çšããã€ã³ã¹ã¿ã³ã¹ããŒã«ãéžæããŸãã [次ãž] ãéžæããŸãã [ã€ã³ã¹ã¿ã³ã¹æ§æ] èšå®ã§ãEC2 ã€ã³ã¹ã¿ã³ã¹ã®ãµã€ãºãšã¿ã€ããéžæããŸããäŸãã°ãGPU ãåããã€ã³ã¹ã¿ã³ã¹ã¿ã€ãã Graviton ããã»ããµã䜿çšããã€ã³ã¹ã¿ã³ã¹ã¿ã€ããéžæã§ããŸããç¹å¥ãªèŠä»¶ã¯ãªãããã¹ãŠã®èšå®ãããã©ã«ãå€ã®ãŸãŸã«ããŸãã [ãããã¯ãŒã¯æ§æ] ã§ãã³ã³ãœãŒã«ã§ã¯æ¢ã« [ããã©ã«ã VPC] ãš [ããã©ã«ãã»ãã¥ãªãã£ã°ã«ãŒã] ãéžæãããŠããŸããæåŸã®ã¹ãããã§ã¯ããã¹ãŠã®èšå®ã確èªããã³ã³ãã¥ãŒãã£ã³ã°ç°å¢ã®äœæãå®äºããŸãã ããã§ãããã²ãŒã·ã§ã³ãã€ã³ãã [ãžã§ããã¥ãŒ] ãéžæããæ¬¡ã« [äœæ] ãéžæããŸãããã®åŸãã³ã³ãã¥ãŒãã£ã³ã°ç°å¢ã«äœ¿çšããã®ãšåããªãŒã±ã¹ãã¬ãŒã·ã§ã³ã¿ã€ã ( Amazon EC2 ) ãéžæããŸãã [ãžã§ããã¥ãŒã®èšå®] ã§ããžã§ããã¥ãŒã®ååãå
¥åããŸãã [æ¥ç¶ãããã³ã³ãã¥ãŒãã£ã³ã°ç°å¢] ããããããŠã³ã§ãäœæããã°ããã®ã³ã³ãã¥ãŒãã£ã³ã°ç°å¢ãéžæãããã¥ãŒã®äœæãå®äºããŸãã ããã²ãŒã·ã§ã³ãã€ã³ãã [ãžã§ãå®çŸ©] ãéžæããæ¬¡ã« [äœæ] ãéžæããŸããåãšåæ§ã«ããªãŒã±ã¹ãã¬ãŒã·ã§ã³ã¿ã€ããšã㊠[Amazon EC2] ãéžæããŸãã è€æ°ã®ã³ã³ããã䜿çšããã«ã¯ã [åŸæ¥ã® containerProperties æ§é ã䜿çš] ãªãã·ã§ã³ãç¡å¹ã«ããŠã次ã®ã¹ãããã«é²ã¿ãŸããããã©ã«ãã§ã¯ãã¢ã«ãŠã³ãã«åŸæ¥ã®ãžã§ãå®çŸ©ãæ¢ã«ååšããå Žåãã³ã³ãœãŒã«ã¯åŸæ¥ã®åäžã³ã³ãããžã§ãå®çŸ©ãäœæããŸããç§ã®å Žåã¯ãã®ããã«ãªããŸããåŸæ¥ã®ãžã§ãå®çŸ©ãæããªãã¢ã«ãŠã³ãã®å Žåãã³ã³ãœãŒã«ã§ã¯ãã®ãªãã·ã§ã³ãç¡å¹ã«ãªã£ãŠããŸãã ãžã§ãå®çŸ©ã®ååãå
¥åããŸãããã®åŸããã®ãžã§ãã«ã©ã®èš±å¯ãå¿
èŠããèããå¿
èŠããããŸãããã®ãžã§ãã«äœ¿çšããã³ã³ããã€ã¡ãŒãžã¯ã Amazon ECR ãã©ã€ããŒããªããžããªã«ä¿åãããŠããŸããAWS Batch ããããã®ã€ã¡ãŒãžãã³ã³ãã¥ãŒãã£ã³ã°ç°å¢ã«ããŠã³ããŒãã§ããããã«ããã«ã¯ã [ã¿ã¹ã¯ããããã£] ã»ã¯ã·ã§ã³ã§ãECR ãªããžããªã«å¯Ÿããèªã¿åãå°çšã¢ã¯ã»ã¹ãä»äžãã [å®è¡ããŒã«] ãéžæããŸããã·ãã¥ã¬ãŒã·ã§ã³ã³ãŒã㯠AWS API ãåŒã³åºããŠããªãããã [ã¿ã¹ã¯ããŒã«] ãèšå®ããå¿
èŠã¯ãããŸãããäŸãã°ãã³ãŒããçµæã Amazon Simple Storage Service (Amazon S3) ãã±ããã«ã¢ããããŒãããå Žåããã®ããã®èš±å¯ãä»äžããããŒã«ãããã§éžæã§ããŸãã æ¬¡ã®ã¹ãããã§ã¯ããã®ãžã§ãã§äœ¿çšããã 2 ã€ã®ã³ã³ãããèšå®ããŸãã1 ã€ç®ã¯ maze-model ã§ããååãšç»åã®å Žæãå
¥åããŸããããã§ã¯ãvCPUãã¡ã¢ãªãGPU ã®èгç¹ããã³ã³ããã®ãªãœãŒã¹èŠä»¶ãæå®ã§ããŸããããã¯ã ECS ã¿ã¹ã¯ ã®ã³ã³ããã®èšå®ã«äŒŒãŠããŸãã ãšãŒãžã§ã³ãçšã® 2 çªç®ã®ã³ã³ããã远å ãã以åãšåæ§ã«ååãã€ã¡ãŒãžã®å ŽæããªãœãŒã¹èŠä»¶ãå
¥åããŸãããšãŒãžã§ã³ãã¯è¿·è·¯ã®éå§çŽåŸã«è¿·è·¯ã«ã¢ã¯ã»ã¹ããå¿
èŠãããããã [äŸåé¢ä¿] ã»ã¯ã·ã§ã³ã䜿çšããŠã³ã³ããã®äŸåé¢ä¿ã远å ããŸããã³ã³ããåãšã㊠maze-model ãéžæããæ¡ä»¶ãšã㊠START ãéžæããŸãããã®äŸåé¢ä¿ã远å ããªãå Žåã maze-model ã³ã³ãããå®è¡ãããŠå¿çã§ããããã«ãªãåã«ã agent ã³ã³ããã倱æããå¯èœæ§ããããŸãããã®ãžã§ãå®çŸ©ã§ã¯äž¡æ¹ã®ã³ã³ããã«å¿
é ã®ãã©ã°ãèšå®ãããŠããããããžã§ãå
šäœã倱æããŠçµäºããŸãã ãã¹ãŠã®èšå®ã確èªãããžã§ãå®çŸ©ãå®äºããŸããããã§ãä»äºãå§ããããšãã§ããŸãã ããã²ãŒã·ã§ã³ãã€ã³ã® [ãžã§ã] ã»ã¯ã·ã§ã³ã§ãæ°ãããžã§ããéä¿¡ããŸããååãå
¥åãããžã§ããã¥ãŒãšäœæããã°ããã®ãžã§ãå®çŸ©ãéžæããŸãã æ¬¡ã®ã¹ãããã§ã¯ãèšå®ãäžæžãããŠãžã§ããäœæããå¿
èŠã¯ãããŸãããæ°ååŸããžã§ãã¯æåãã2 ã€ã®ã³ã³ããã®ãã°ã«ã¢ã¯ã»ã¹ã§ããããã«ãªããŸããã ãšãŒãžã§ã³ãã¯è¿·è·¯ã解決ããã®ã§ããã°ãããã¹ãŠã®è©³çްãååŸã§ããŸãããšãŒãžã§ã³ããã©ã®ããã«éå§ãããããŒãååŸããåºå£ãèŠã€ãããã瀺ããžã§ãã®åºåãæ¬¡ã«ç€ºããŸãã SIZE {'width': 80, 'height': 20} START {'x': 0, 'y': 18} (32, 2) key found (79, 16) exit Solution length: 437 [(0, 18), (1, 18), (0, 18), ..., (79, 14), (79, 15), (79, 16)] ãããã§ã¯ãèµ€ãã¢ã¹ã¿ãªã¹ã¯ ( * ) ã¯ãéå§ ( S )ãã㌠( K )ãããã³çµäº ( E ) ã®å Žæéã§ãšãŒãžã§ã³ãããã©ããã¹ã瀺ããŠããŸãã ãµã€ãã«ãŒã³ã³ããã«ãããªãã¶ãŒãããªãã£ã®åäž è€æ°ã®ã³ã³ããŒãã³ãã䜿çšããŠè€éãªãžã§ããå®è¡ããå Žåããããã®ã³ã³ããŒãã³ããäœãè¡ã£ãŠããããããæç¢ºã«ææ¡ããããšãã§ããŸããäŸãã°ããšã©ãŒãããã©ãŒãã³ã¹ã®åé¡ãçºçããå Žåããã®æ
å ±ã¯åé¡ãçºçããå Žæãšãã®å
容ãèŠã€ããã®ã«åœ¹ç«ã¡ãŸãã ã¢ããªã±ãŒã·ã§ã³ãã€ã³ã¹ãã«ã¡ã³ãåããã«ã¯ã AWS Distro for OpenTelemetry ã䜿çšããŸãã ãŸãã agent ã³ã³ãããš maze-model ã³ã³ãããæŽæ°ããŠã ãã®èšäºã§èª¬æãããŠãã Python èªåã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ã䜿çšããŸã ãGoãJavaãJavaScript ãªã©ãä»ã®ãã©ãããã©ãŒã ã«ãåæ§ã®ãã¥ãŒããªã¢ã«ããããŸããèªåã®ã¢ããªã±ãŒã·ã§ã³ã«åºæã®æ
å ±ãååŸããããã«ã ã³ãŒããæåã§ã€ã³ã¹ãã«ã¡ã³ãåãã ãšãããªãã·ã§ã³ããããŸãã ãã®åŸã Amazon ECR Public Gallery ã® AWS Distro for OpenTelemetry Collector ã䜿çšããŠãµã€ãã«ãŒã³ã³ããã远å ããŸãã collector ã³ã³ããã¯ãä»ã®ã³ã³ãããããã¬ã¡ããªããŒã¿ãåä¿¡ãããã¬ãŒã¹ã AWS X-Ray ã«éä¿¡ããŠãã¡ããªã¯ã¹ã Amazon CloudWatch ã Amazon Managed Service for Prometheus ããŸãã¯ã»ã«ããããŒãžã Prometheus ã«éä¿¡ããŸããOpenTelemetry ã䜿çšãããšã è€æ°ã®ã¢ãã¿ãªã³ã°ããã³ãªãã¶ãŒãããªãã£ãã©ãããã©ãŒã ãšã®ããŒã¿ã®å
±æã容æã«ãªããŸãã ãã®æ¹æ³ã§åéããããã¬ã¡ããªããŒã¿ã䜿çšãããšãäœãèµ·ãã£ãŠããããããè¯ãçè§£ããåé¡ã解決ããããã®æéãççž®ããã®ã«åœ¹ç«ã€ããã·ã¥ããŒã (äŸãã°ãCloudWatch ãŸã㯠Amazon Managed Grafana ãå©çš) ãã¢ã©ãŒã (CloudWatch ãŸã㯠Prometheus ãå©çš) ãèšå®ã§ããŸããããäžè¬çã«ã¯ããµã€ãã«ãŒã³ã³ããã¯ãAWS Batch ãžã§ãããã®ãã¬ã¡ããªããŒã¿ãã¢ãã¿ãªã³ã°ããã³ãªãã¶ãŒãããªãã£ãã©ãããã©ãŒã ã«çµ±åããã®ã«åœ¹ç«ã¡ãŸãã ç¥ã£ãŠããã¹ãããš AWS Batch ã«ãããã«ãã³ã³ãããžã§ãã®ãµããŒãã¯çŸåšãBatch ãæäŸãããŠãããã¹ãŠã® AWS ãªãŒãžã§ã³ ã«ãããŠã AWS ãããžã¡ã³ãã³ã³ãœãŒã« ã AWS ã³ãã³ãã©ã€ã³ã€ã³ã¿ãŒãã§ã€ã¹ (AWS CLI) ã AWS SDK ã§ãå©çšããã ããŸãã詳现ã«ã€ããŠã¯ã AWS ãµãŒãã¹ (ãªãŒãžã§ã³å¥) ãã芧ãã ããã AWS Batch ã§ãã«ãã³ã³ãããžã§ãã䜿çšããå Žåãè¿œå æéã¯ããããŸãããå®éãAWS Batch ã®å©çšã«ã¯è¿œå æéã¯ããããŸããããæ¯æãããã ãã®ã¯ãEC2 ã€ã³ã¹ã¿ã³ã¹ã Fargate ã³ã³ãããªã©ãã¢ããªã±ãŒã·ã§ã³ãä¿åããã³å®è¡ããããã«äœæãã AWS ãªãœãŒã¹ã®æéã®ã¿ã§ããã³ã¹ããæé©åããããã«ãã³ã³ãã¥ãŒãã£ã³ã°ç°å¢ã§ ãªã¶ãŒããã€ã³ã¹ã¿ã³ã¹ ã Savings Plan ãEC2 ã¹ãããã€ã³ã¹ã¿ã³ã¹ãFargate ã䜿çšã§ããŸãã ãã«ãã³ã³ãããžã§ãã䜿çšãããšããžã§ãã®æºåäœæ¥ãæžãããšã§éçºæéãççž®ãããã»ããè€æ°ã®ããŒã ã®äœæ¥ã 1 ã€ã®ã³ã³ããã«ããŒãžããã«ã¹ã¿ã ããŒã«ã®å¿
èŠæ§ããªããªããŸãããŸããã³ã³ããŒãã³ãã®è²¬ä»»ãæç¢ºã«å®çŸ©ããããšã§ DevOps ãç°¡çŽ åããããŒã ãä»ã®äœæ¥ã«ç
©ããããããšãªãèªåã®å°éåéã®åé¡ãè¿
éã«ç¹å®ããŠä¿®æ£ã§ããããã«ããŸãã 詳现ã«ã€ããŠã¯ãã AWS Batch ãŠãŒã¶ãŒã¬ã€ã ãã§ãã«ãã³ã³ãããžã§ããèšå®ããæ¹æ³ãã芧ãã ããã â Danilo åæã¯ ãã¡ã ã§ãã