一个完整的加速小项目
🔴 这一节的 Python 题会**在运行时调 gcc 现编一个 .so,再用 ctypes 加载进来**——真的跨语言调用,不是假装。判题机需要 gcc、一个可写的临时目录,以及允许 Python 起子进程。⚠️ 这条路线**一个答案都不是耗时**。耗时跟机器、跟负载、跟编译器都有关,换台机器数字就变了。**能当答案的只有"走了多少步"和"两边结果一不一样"。**两个热点函数,两条验证:
import ctypes, os, subprocess, tempfile
def build_c(src, name="m"):
"""把一段 C 现场编成 .so,交回加载好的库。
判题机需要 gcc 和一个可写的临时目录。"""
d = tempfile.mkdtemp()
c_path = os.path.join(d, name + ".c")
so_path = os.path.join(d, name + ".so")
with open(c_path, "w") as f:
f.write(src)
subprocess.run(["gcc", "-shared", "-fPIC", "-O2", "-o", so_path, c_path],
check=True, capture_output=True)
return ctypes.CDLL(so_path)
C_SRC = r"""
long count_above(const int *a, int n, int line) {
long c = 0;
for (int i = 0; i < n; i++) if (a[i] > line) c++;
return c;
}
long sum_sq(const int *a, int n) {
long s = 0;
for (int i = 0; i < n; i++) s += (long)a[i] * a[i];
return s;
}
"""
data = list(range(1, 101))
LINE = 50
# 纯 Python 版(基准)
def py_count_above(xs, line):
return sum(1 for x in xs if x > line)
def py_sum_sq(xs):
return sum(x * x for x in xs)
built = 0
try:
lib = build_c(C_SRC)
built = 1
except Exception:
built = 0
lib.count_above.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.c_int, ctypes.c_int]
lib.count_above.restype = ctypes.c_long
lib.sum_sq.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.c_int]
lib.sum_sq.restype = ctypes.c_long
Arr = ctypes.c_int * len(data)
buf = Arr(*data)
c1 = lib.count_above(buf, len(data), LINE)
c2 = lib.sum_sq(buf, len(data))
same1 = int(c1 == py_count_above(data, LINE))
same2 = int(c2 == py_sum_sq(data))
print(f"{built}/{c1}/{c2}/{same1}/{same2}")
全部评论