Commit a5d5ab27 authored by Artur Paszkiewicz's avatar Artur Paszkiewicz Committed by Tomasz Zawadzki
Browse files

examples/accel/perf: add support for xor



Change-Id: I0a9216945f5877af80d911b46f988a440e855fd4
Signed-off-by: default avatarArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16395


Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
parent b41efae2
Loading
Loading
Loading
Loading
+58 −5
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include "spdk/accel.h"
#include "spdk/crc32.h"
#include "spdk/util.h"
#include "spdk/xor.h"

#define DATA_PATTERN 0x5a
#define ALIGN_4K 0x1000
@@ -32,6 +33,7 @@ static uint32_t g_crc32c_seed = 0;
static uint32_t g_chained_count = 1;
static int g_fail_percent_goal = 0;
static uint8_t g_fill_pattern = 255;
static uint32_t g_xor_src_count = 2;
static bool g_verify = false;
static const char *g_workload_type = NULL;
static enum accel_opcode g_workload_selection;
@@ -70,6 +72,7 @@ struct ap_task {
	void			*src;
	struct iovec		*src_iovs;
	uint32_t		src_iovcnt;
	void			**sources;
	struct iovec		*dst_iovs;
	uint32_t		dst_iovcnt;
	void			*dst;
@@ -121,6 +124,8 @@ dump_user_config(void)
		printf("Fill pattern:   0x%x\n", g_fill_pattern);
	} else if ((g_workload_selection == ACCEL_OPC_COMPARE) && g_fail_percent_goal > 0) {
		printf("Failure inject: %u percent\n", g_fail_percent_goal);
	} else if (g_workload_selection == ACCEL_OPC_XOR) {
		printf("Source buffers: %u\n", g_xor_src_count);
	}
	if (g_workload_selection == ACCEL_OPC_COPY_CRC32C) {
		printf("Vector size:    %u bytes\n", g_xfer_size_bytes);
@@ -151,11 +156,12 @@ usage(void)
	printf("\t[-n number of channels]\n");
	printf("\t[-o transfer size in bytes (default: 4KiB. For compress/decompress, 0 means the input file size)]\n");
	printf("\t[-t time in seconds]\n");
	printf("\t[-w workload type must be one of these: copy, fill, crc32c, copy_crc32c, compare, compress, decompress, dualcast\n");
	printf("\t[-w workload type must be one of these: copy, fill, crc32c, copy_crc32c, compare, compress, decompress, dualcast, xor\n");
	printf("\t[-l for compress/decompress workloads, name of uncompressed input file\n");
	printf("\t[-s for crc32c workload, use this seed value (default 0)\n");
	printf("\t[-P for compare workload, percentage of operations that should miscompare (percent, default 0)\n");
	printf("\t[-f for fill workload, use this BYTE value (default 255)\n");
	printf("\t[-x for xor workload, use this number of source buffers (default, minimum: 2)]\n");
	printf("\t[-y verify result if this switch is on]\n");
	printf("\t[-a tasks to allocate per core (default: same value as -q)]\n");
	printf("\t\tCan be used to spread operations across a wider range of memory.\n");
@@ -176,6 +182,7 @@ parse_args(int argc, char *argv)
	case 'q':
	case 's':
	case 't':
	case 'x':
		argval = spdk_strtol(optarg, 10);
		if (argval < 0) {
			fprintf(stderr, "-%c option must be non-negative.\n", argc);
@@ -218,6 +225,9 @@ parse_args(int argc, char *argv)
	case 't':
		g_time_in_sec = argval;
		break;
	case 'x':
		g_xor_src_count = argval;
		break;
	case 'y':
		g_verify = true;
		break;
@@ -239,6 +249,8 @@ parse_args(int argc, char *argv)
			g_workload_selection = ACCEL_OPC_COMPRESS;
		} else if (!strcmp(g_workload_type, "decompress")) {
			g_workload_selection = ACCEL_OPC_DECOMPRESS;
		} else if (!strcmp(g_workload_type, "xor")) {
			g_workload_selection = ACCEL_OPC_XOR;
		} else {
			usage();
			return 1;
@@ -356,7 +368,20 @@ _get_task_data_bufs(struct ap_task *task)
			memset(task->src_iovs[i].iov_base, DATA_PATTERN, g_xfer_size_bytes);
			task->src_iovs[i].iov_len = g_xfer_size_bytes;
		}
	} else if (g_workload_selection == ACCEL_OPC_XOR) {
		assert(g_xor_src_count > 1);
		task->sources = calloc(g_xor_src_count, sizeof(*task->sources));
		if (!task->sources) {
			return -ENOMEM;
		}

		for (i = 0; i < g_xor_src_count; i++) {
			task->sources[i] = spdk_dma_zmalloc(g_xfer_size_bytes, 0, NULL);
			if (!task->sources[i]) {
				return -ENOMEM;
			}
			memset(task->sources[i], DATA_PATTERN, g_xfer_size_bytes);
		}
	} else {
		task->src = spdk_dma_zmalloc(g_xfer_size_bytes, 0, NULL);
		if (task->src == NULL) {
@@ -388,7 +413,8 @@ _get_task_data_bufs(struct ap_task *task)
	}

	/* For dualcast 2 buffers are needed for the operation.  */
	if (g_workload_selection == ACCEL_OPC_DUALCAST) {
	if (g_workload_selection == ACCEL_OPC_DUALCAST ||
	    (g_workload_selection == ACCEL_OPC_XOR && g_verify)) {
		task->dst2 = spdk_dma_zmalloc(g_xfer_size_bytes, align, NULL);
		if (task->dst2 == NULL) {
			fprintf(stderr, "Unable to alloc dst buffer\n");
@@ -474,6 +500,10 @@ _submit_single(struct worker_thread *worker, struct ap_task *task)
		rc = spdk_accel_submit_decompress(worker->ch, task->dst_iovs, task->dst_iovcnt, task->src_iovs,
						  task->src_iovcnt, NULL, flags, accel_done, task);
		break;
	case ACCEL_OPC_XOR:
		rc = spdk_accel_submit_xor(worker->ch, task->dst, task->sources, g_xor_src_count,
					   g_xfer_size_bytes, accel_done, task);
		break;
	default:
		assert(false);
		break;
@@ -503,12 +533,19 @@ _free_task_buffers(struct ap_task *task)
			}
			free(task->src_iovs);
		}
	} else if (g_workload_selection == ACCEL_OPC_XOR) {
		if (task->sources) {
			for (i = 0; i < g_xor_src_count; i++) {
				spdk_dma_free(task->sources[i]);
			}
			free(task->sources);
		}
	} else {
		spdk_dma_free(task->src);
	}

	spdk_dma_free(task->dst);
	if (g_workload_selection == ACCEL_OPC_DUALCAST) {
	if (g_workload_selection == ACCEL_OPC_DUALCAST || g_workload_selection == ACCEL_OPC_XOR) {
		spdk_dma_free(task->dst2);
	}
}
@@ -599,6 +636,15 @@ accel_done(void *arg1, int status)
				worker->xfer_failed++;
			}
			break;
		case ACCEL_OPC_XOR:
			if (spdk_xor_gen(task->dst2, task->sources, g_xor_src_count,
					 g_xfer_size_bytes) != 0) {
				SPDK_ERRLOG("Failed to generate xor for verification\n");
			} else if (memcmp(task->dst, task->dst2, g_xfer_size_bytes)) {
				SPDK_NOTICELOG("Data miscompare\n");
				worker->xfer_failed++;
			}
			break;
		default:
			assert(false);
			break;
@@ -1077,7 +1123,7 @@ main(int argc, char **argv)
	spdk_app_opts_init(&g_opts, sizeof(g_opts));
	g_opts.name = "accel_perf";
	g_opts.reactor_mask = "0x1";
	if (spdk_app_parse_args(argc, argv, &g_opts, "a:C:o:q:t:yw:P:f:T:l:", NULL, parse_args,
	if (spdk_app_parse_args(argc, argv, &g_opts, "a:C:o:q:t:yw:P:f:T:l:x:", NULL, parse_args,
				usage) != SPDK_APP_PARSE_ARGS_SUCCESS) {
		g_rc = -1;
		goto cleanup;
@@ -1090,7 +1136,8 @@ main(int argc, char **argv)
	    (g_workload_selection != ACCEL_OPC_COMPARE) &&
	    (g_workload_selection != ACCEL_OPC_COMPRESS) &&
	    (g_workload_selection != ACCEL_OPC_DECOMPRESS) &&
	    (g_workload_selection != ACCEL_OPC_DUALCAST)) {
	    (g_workload_selection != ACCEL_OPC_DUALCAST) &&
	    (g_workload_selection != ACCEL_OPC_XOR)) {
		usage();
		g_rc = -1;
		goto cleanup;
@@ -1114,6 +1161,12 @@ main(int argc, char **argv)
		goto cleanup;
	}

	if (g_workload_selection == ACCEL_OPC_XOR && g_xor_src_count < 2) {
		usage();
		g_rc = -1;
		goto cleanup;
	}

	g_rc = spdk_app_start(&g_opts, accel_perf_prep, NULL);
	if (g_rc) {
		SPDK_ERRLOG("ERROR starting application\n");
+2 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ run_test "accel_copy_crc32c" $SPDK_EXAMPLE_DIR/accel_perf -t 1 -w copy_crc32c -y
run_test "accel_copy_crc32c_C2" $SPDK_EXAMPLE_DIR/accel_perf -t 1 -w copy_crc32c -y -C 2
run_test "accel_dualcast" $SPDK_EXAMPLE_DIR/accel_perf -t 1 -w dualcast -y
run_test "accel_compare" $SPDK_EXAMPLE_DIR/accel_perf -t 1 -w compare -y
run_test "accel_xor" $SPDK_EXAMPLE_DIR/accel_perf -t 1 -w xor -y
run_test "accel_xor" $SPDK_EXAMPLE_DIR/accel_perf -t 1 -w xor -y -x 3
# do not run compress/decompress unless ISAL is installed
if [[ $CONFIG_ISAL == y ]]; then
	run_test "accel_comp" $SPDK_EXAMPLE_DIR/accel_perf -t 1 -w compress -l $testdir/bib