summaryrefslogtreecommitdiffstats
path: root/tools/cuda-ab/p2/src/p2_streams.cu
blob: 09d6ed3238afa7f59238483a176a719acdc0cee0 (plain)
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// SPDX-License-Identifier: BSD-3-Clause
/*
 * p2_streams - three created streams, two kernels per stream (scale then
 * add), independent 1024-float buffers, per-stream events.
 *
 * Expected value per element: ((i % 100) * 2.0f) + 1.0f (exact in fp32).
 * After all streams complete, each event must query as complete.
 * Device memory: 3 x 4 KB (3 pages).
 */
#include "common.h"

#define SN 1024
#define NS 3

__global__ void scale(float *x, float s, int n)
{
	int i = blockIdx.x * blockDim.x + threadIdx.x;

	if (i < n)
		x[i] = x[i] * s;
}

__global__ void addv(float *x, float v, int n)
{
	int i = blockIdx.x * blockDim.x + threadIdx.x;

	if (i < n)
		x[i] = x[i] + v;
}

static void fill(float *h, int n)
{
	for (int i = 0; i < n; i++)
		h[i] = (float)(i % 100);
}

static float expected1(int i)
{
	return ((float)(i % 100) * 2.0f) + 1.0f;
}

int main(int argc, char **argv)
{
	float *h = (float *)malloc(sizeof(float) * SN);
	float *got = (float *)malloc(sizeof(float) * SN);
	int bad = 0;

	if (!h || !got)
		return 1;
	fill(h, SN);

	if (p2_emit_mode(argc, argv)) {
		printf("RESULT streams nstreams=%d launches=%d n=%d bad=0\n",
		       NS, NS * 2, SN);
		printf("RESULT streams events=%d bad=0\n", NS);
		free(h); free(got);
		return p2_status(0);
	}

	p2_device_info();

	cudaStream_t st[NS];
	cudaEvent_t ev[NS];
	float *d_x[NS];

	for (int k = 0; k < NS; k++) {
		P2_CHECK(cudaStreamCreate(&st[k]));
		P2_CHECK(cudaEventCreate(&ev[k]));
		P2_CHECK(cudaMalloc(&d_x[k], sizeof(float) * SN));
		P2_CHECK(cudaMemcpyAsync(d_x[k], h, sizeof(float) * SN,
					 cudaMemcpyHostToDevice, st[k]));
		scale<<<(SN + 255) / 256, 256, 0, st[k]>>>(d_x[k], 2.0f, SN);
		addv<<<(SN + 255) / 256, 256, 0, st[k]>>>(d_x[k], 1.0f, SN);
		P2_CHECK(cudaGetLastError());
		P2_CHECK(cudaEventRecord(ev[k], st[k]));
	}

	int ibad = 0;

	for (int k = 0; k < NS; k++) {
		cudaError_t q;
		int sbad = 0;

		P2_CHECK(cudaStreamSynchronize(st[k]));
		P2_CHECK(cudaMemcpy(got, d_x[k], sizeof(float) * SN,
				    cudaMemcpyDeviceToHost));
		for (int i = 0; i < SN; i++)
			if (got[i] != expected1(i))
				sbad++;
		q = cudaEventQuery(ev[k]);
		if (q != cudaSuccess)
			sbad++;
		printf("RESULT streams stream=%d query_rc=%d bad=%d\n", k, (int)q,
		       sbad);
		ibad += sbad;
	}
	printf("RESULT streams nstreams=%d launches=%d n=%d bad=%d\n",
	       NS, NS * 2, SN, ibad);
	printf("RESULT streams events=%d bad=%d\n", NS, ibad == 0 ? 0 : 1);
	bad = ibad;

	for (int k = 0; k < NS; k++) {
		cudaEventDestroy(ev[k]);
		cudaStreamDestroy(st[k]);
		cudaFree(d_x[k]);
	}
	free(h); free(got);
	return p2_status(bad);
}