每个小妖都在干什么?
怎么让他们发挥出最大的骚扰勇者的潜力?
这是每一个有志之魔王需要考虑的问题。
因此,本王创建了⏲的使魔,附着在小怪物们身上。这样, 每只怪的效率也就一目了然了。
$\Large\color{blue}{【时计塔的使魔😈】}$
Cuda世界的时间流逝,在冒险大陆不可预知。
因此本王创建了使魔,指令开始之时,向cuda大陆记录时间,结束时再记录一次,一来一回,相减得到的就是耗时。
本王将其编写成了一套法阵,待我吟唱 ————
#include "utils.h"
#include <map>
/*
计时使魔:
开始计时时:调用Start;
结束计时时:调用Tick;
可以实现连续计时, 例如:
Start();
doA;
Tick(); //得到A耗时
doB;
Tick(); //得到B耗时
*/
class TImeSerVItor {
public:
TImeSerVItor() {
CHECK(cudaEventCreate(&start_));
CHECK(cudaEventCreate(&stop_));
}
~TImeSerVItor() {
CHECK(cudaEventDestroy(&start_));
CHECK(cudaEventDestroy(&stop_));
}
void Start() {
CHECK(cudaEventRecord(start_));
cudaEventQuery(start_);
}
void Tick() {
CHECK(cudaEventRecord(stop_));
CHECK(cudaEventSynchronize(stop_));
float elapsed_time;
CHECK(cudaEventElapsedTime(&elapsed_time, start_, stop_));
printf("total cost is %f\n", elapsed_time);
CHECK(cudaEventRecord(start_));
cudaEventQuery(start_);
}
private:
cudaEvent_t start_, stop_;
};
$\Large\color{pink}{【批量测试🏭】}$
有了⌚😈相助, 就能对魔兵分门别类,进行一一考核了。
以魔理揣度,每个魔兵思考计算得越多,用来对付勇者就越有效率。
若是本王千辛万苦申请来魔兵,他们单纯搬运指令,就走完了任务流程,那可就大大地浪费了。
初级魔兵需要思考,使用魔法A能造成广谱地图N个地址的伤害,魔法B会造成另外一些伤害。
那么,有多少伤害?
这个地图多大合适?每个小兵又处理多大范围合适?
为此本王设置了可变法阵,逐步记数;
/*处理相加的核函数*/
void __global__ add(double *x, double *y, double *z, const int N, const int step) {
int idx = blockIdx.x;
while (idx < N) {
z[idx] = x[idx] + y[idx];
idx += step;
}
}
int main() {
std::map<int, int> a;
int sum = 0;
int N = 10000;
double **x, **y, **res;
double src_x[1000000], src_y[1000000], src_z[1000000];
for (int i=0; i<20000; i++) {
src_x[i] = random() % 1000;
src_y[i] = random() % 1000;
}
for (int step = N; step < 10*N; step += N) {
CHECK(cudaMalloc((void **)&x, N));
CHECK(cudaMalloc((void **)&y, N));
CHECK(cudaMalloc((void **)&res, N));
CHECK(cudaMemcpy((void*)x, src_x, N, ::cudaMemcpyDefault));
CHECK(cudaMemcpy((void*)y, src_y, N, ::cudaMemcpyDefault));
printf("dealing step N %d\n", step);
TImeSerVItor ti;
ti.Start();
for (int i=0; i<N; i++) {
src_z[i] = src_x[i] + src_y[i];
}
ti.Tick();
int block_num = 1000;
add<<< block_num, 1>>>(*x, *y, *res, N, (N / block_num) + 1);
ti.Tick();
CHECK(cudaFree(x));
CHECK(cudaFree(y));
CHECK(cudaFree(res));
CHECK(cudaStreamSynchronize(0));
}
}
$\Large\color{red}{【计算の王道】}$
以上的阵式只是一个例子,经过更为复杂的多轮验证,本王得到了以下结论:
- 【算术强度】指令传输需要耗时,因此每个小兵需要尽量发挥复杂的计算效力,弥补搬运时的时间耗损
- 【并发数量】cuda大陆下,各小兵自行其事,可以在资源足够的情况下分配更多的小兵;
另外,根据经验,往返两个大陆间的信息通道带宽,只有CUDA大陆内部的几十分之一,所以两方的数据传输需要尽可能少,哪怕是为此需要分配一些cuda大陆执行较慢的操作。
下一步,本王就该详细拆开每个使魔的构造,让他们更听话了。
沙发