ActPi's Blog

Share & Record

DOTA2 TI14新赛制与往年对比深度分析报告

引言:TI14赛制改革背景与核心目标

2025年国际邀请赛(TI14)作为DOTA2顶级赛事的第十四届盛会,于9月4日至14日在德国汉堡拉开帷幕。由Valve与PGL合作举办的本届赛事,不仅是TI系列首次重回汉堡,更在赛制层面迎来颠覆性变革——以瑞士轮赛制全面取代沿用十余年的传统小组赛,这一调整被官方定义为“回归竞技本质的战略优化”[1][2]。16支全球顶尖战队将通过“国际邀请赛之路”(9月4-7日)与“国际邀请赛”(9月11-14日)两个阶段的角逐,争夺基础奖金池160万美元及众筹后预计超200万美元的总奖金[3]。这一改革的背后,是Valve对往届赛事体系深层矛盾的系统性回应。

改革背景:传统赛制的结构性痛点

长期以来,TI系列赛事的小组赛阶段饱受争议。传统循环赛制下,“算分放水”现象屡见不鲜——尤其在小组赛最后一天,已确定出线或淘汰的队伍往往缺乏竞争动力,导致比赛观赏性大幅下降[4]。更严重的是,强弱队伍过早相遇时常造成悬殊比分(如往届出现的1-9碾压局),这类“垃圾时间”不仅消耗观众耐心,更削弱了比赛结果对晋级命运的实质影响[5]。TI13赛季爆发的赛制争议进一步暴露了循环赛的缺陷:部分场次因“仅与场外队伍积分相关”而丧失竞技意义,引发战队与观众对公平性的质疑[6]。

阅读全文 »

问题

在安装docker环境后 mpi 多机并行环境运行程序失效,mpi 程序拉起后无后续执行的信息,导致进程卡住

排查思路

  1. 检查 ssh 均正常,可以免密登陆
  2. 通过 pstree 查看 mpi 进程树,可以看到主副节点均能发现有进程占用
  3. 打开 mpi 详细调试日志
    a. export I_MPI_DEBUG=5
    b. export I_MPI_HYDRA_DEBUG=on

可以看到输出如下启动时的网卡信息输出后卡住:

1
2
3
[0] MPI startup(): ===== NIC pinning on ubuntu04 =====
[0] MPI startup(): Rank Thread id Pin nic
[0] MPI startup(): 0 0 br-0718f8abdfbb
阅读全文 »

默认的gcc版本是4.8.5,无法编译高版本的glibc 2.28,需要升级到gcc 8以上的版本

升级 gcc

1
2
3
4
5
6
yum -y install centos-release-scl
yum -y install devtoolset-8-gcc devtoolset-8-gcc-c++ devtoolset-8-binutils
scl enable devtoolset-8 bash
echo "source /opt/rh/devtoolset-8/enable" >>/etc/profile
查看是否升级成功
gcc --version

升级 make

注意:make 的版本高于4.4 会造成 glibc 编译时卡在这一行

make[2]: Entering directory '/root/glibc-2.28/stdio-common
所以安装 make 4.2 的版本即可

1
2
3
4
5
6
7
8
9
10
11
wget http://ftp.gnu.org/pub/gnu/make/make-4.2.tar.gz
tar -xzvf make-4.2.tar.gz
cd make-4.2/
mkdir build && cd build
../configure --prefix=/usr/
make
make install
# 删除旧的 make
rm /usr/bin/make
# 拷贝新的
cp make /usr/bin/

升级glibc

1
2
3
4
5
6
7
8
wget https://ftp.gnu.org/gnu/glibc/glibc-2.28.tar.gz
tar -xzvf glibc-2.28.tar.gz
cd glibc-2.28
#创建编译临时目录
mkdir build && cd build
../configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin
make
make install

查询是否升级成功:
strings /lib64/libc.so.6 | grep GLIBC

安装并导入库

安装:pip install python-jenkins

1
import python-jenkins

连接到Jenkins

1
2
3
server = jenkins.Jenkins('https://jenkins.domain.com/',username='username', password='password',timeout =5)
user = server.get_whoami()
print(user)
  1. 获取整个view下的所有任务
1
jobs = server.get_jobs(view_name="my view")
  1. 停用任务
1
2
3
4
5
6
7
for job in jobs:
job_info = server.get_job_info(job['name'])
if job_info['disabled']:
print(f"{job['name']} is already disabled")
else:
print(f"now disable {job['name']}...")
server.disable_job(job['name'])

安装并导入 pandas 库

安装:pip install pandas

1
import pandas as pd

从 csv 文件读取并添加自定义表头

1
2
3
4
5
6
def read_csv_file(csv):
try:
with open(csv, 'r') as f:
return pd.read_csv(f, header=None, names=['a', 'b', 'c', 'd', 'e', 'f'])
except FileNotFoundError:
print(f"Error: File '{csv}' not found.")

将某列数据转换为数字格式,并将无法转换的置0
阅读全文 »

终止运行超时的进程

subprocess 模块主要用于创建子进程,并连接它们的输入、输出和错误管道,获取它们的返回状态,在某种特殊情况下,我们需要对子进程的运行时间做限制,当超时时强制终止并获取输出。
subprocess 模块首先推荐使用的是它的 run 方法,更高级的用法是使用 Popen

Popen 方法语法格式如下

1
subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0,restore_signals=True, start_new_session=False, pass_fds=(),*, encoding=None, errors=None)

常用参数:

  • args:表示要执行的命令,可以是字符串或者序列类型(如:list,元组)
  • bufsize:缓冲区大小。当创建标准流的管道对象时使用,默认-1。
    0:不使用缓冲区
    1:表示行缓冲,仅当universal_newlines=True时可用,也就是文本模式
    正数:表示缓冲区字节大小
    负数:表示使用系统默认的缓冲区大小。
  • stdin、stdout 和 stderr:子进程的标准输入、输出和错误。其值可以是 subprocess.PIPE、subprocess.DEVNULL、一个已经存在的文件描述符、已经打开的文件对象或者 None。subprocess.PIPE 表示为子进程创建新的管道。subprocess.DEVNULL 表示使用 os.devnull。默认使用的是 None,表示什么都不做。另外,stderr 可以合并到 stdout 里一起输出。
  • timeout:设置命令超时时间。如果命令执行时间超时,子进程将被杀死,并弹出 TimeoutExpired 异常。
    阅读全文 »

记录程序的执行时间,并进行单位换算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import datetime


def convert_seconds(seconds):
"""
将给定的秒数转换为小时、分钟和秒。
"""
hour = seconds // 3600
minute = (seconds % 3600) // 60
second = seconds % 60
if hour == 0:
if minute == 0:
run_time = f"{second} 秒"
else:
run_time = f"{minute}{second} 秒"
else:
run_time = f"{hour} 小时 {minute}{second} 秒"

return run_time

def main():
start = datetime.datetime.now()
# do something
end = datetime.datetime.now()

run_time = convert_seconds((end-start).seconds)

问题描述

如下 Shell 脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
do somothing

python script.py
#获取Python命令的退出码
e_code=$?
if [ $e_code -noteq 0 ];then
echo "python script.py failed, exit code is $e_code"
exit 1001
else
echo "python script.py success"
exit 0
fi

在 Jenkins 中执行此脚本时,通过 Shell 调用了 Python 脚本,当 Python 脚本内部异常退出例如遇到 sys.exit(1001),导致异常退出码无法抓取。

原因及解决

这是由于 Jenkins 在执行 shell 脚本时,默认会在命令行中加上 -e 选项,该选项的作用是在脚本中遇到错误时会立即退出。这样可以确保在脚本发生错误时及时停止执行,避免继续执行可能导致更严重问题的命令。

在 Shell 脚本前手动添加 set +e 来禁用该选项。即可继续执行后续命令。

PS:Jenkins 在执行 shell 脚本时,默认会在命令行中加上 -xe 选项, 该选项的作用是在脚本运行时打印每一行命令以及运行中遇到错误时会立即退出。这样可以确保在脚本发生错误立即中断。

用于在指定路径查询日志文件并返回对应的完整路径列表

用 os path

1
2
3
4
5
6
7
8
9
10
11
12
13
def get_log_file(log_dir):
"""
从指定目录查找后缀为 .log 的文件
:param log_dir: 待查找的目录
:return: 返回所有的 .log 文件路径列表
"""
log_files = []
for root, dirs, files in os.walk(log_dir):
for file in files:
if file.endswith(".log"):
log_files.append(os.path.join(root,file))

return log_files

用 pathlib

1
2
3
4
5
6
7
8
9
def get_log_file(rootdir):
log_files = []
root_path = Path(rootdir)
print("--->开始到算例库查找算例文件: ")
### find inp
for file in root_path.rglob('*.log'):
log_files.append(file)

return log_files

改动 if file.endswith(".log") 可查找任意后缀的文件。

需求

当向 gitlab 推送 tag 时自动生成 Release 发布包的自动 CI 功能

实现

首先在对应仓库生成一个 Project Access Token,授权 api 和 write_repository 权限,然后在仓库的设置-CI/CD 新增 Variable 名称为 ACCESS_TOKEN、值为上一步生成的 Token。

  1. 当有推送 tag 时、自动触发 gitlab CI 任务
    编写 CI 配置文件 .gitlab-ci.yml

    1
    2
    3
    4
    5
    6
    7
    8
    Create_Release:
    stage: deploy
    tags:
    - runner # 指定runner
    only:
    - tags # 仅对推送 tag 时触发
    script:
    - bash deploy_release.sh
    阅读全文 »
0%