diff --git a/fabtests/Makefile.am b/fabtests/Makefile.am index b97ca169e5f..6d830668833 100644 --- a/fabtests/Makefile.am +++ b/fabtests/Makefile.am @@ -229,6 +229,8 @@ libfabtests_la_SOURCES = \ common/hmem_ze.c \ common/hmem_neuron.c \ common/hmem_synapseai.c \ + common/ofi_atomic.c \ + include/ofi_atomic.h \ include/shared.h \ include/ft_list.h \ include/hmem.h \ @@ -468,8 +470,6 @@ unit_fi_setopt_test_LDADD = libfabtests.la ubertest_fi_ubertest_SOURCES = \ ubertest/fabtest.h \ - ubertest/ofi_atomic.h \ - ubertest/ofi_atomic.c \ ubertest/uber.c \ ubertest/connect.c \ ubertest/cq.c \ diff --git a/fabtests/Makefile.win b/fabtests/Makefile.win index dc3a28fe0b6..da244c78735 100644 --- a/fabtests/Makefile.win +++ b/fabtests/Makefile.win @@ -46,7 +46,7 @@ CFLAGS = $(CFLAGS) /O2 /MT basedeps = common\hmem.c common\shared.c \ common\windows\getopt.c common\windows\osd.c \ common\hmem_cuda.c common\hmem_rocr.c common\hmem_ze.c \ - common\hmem_neuron.c common\hmem_synapseai.c + common\hmem_neuron.c common\hmem_synapseai.c common\ofi_atomic.c includes = /Iinclude /Iinclude\windows /I..\include /FIft_osd.h \ /Iinclude\windows\getopt /Imultinode\include diff --git a/fabtests/common/hmem.c b/fabtests/common/hmem.c index 1c724510c4e..0cd736441b4 100644 --- a/fabtests/common/hmem.c +++ b/fabtests/common/hmem.c @@ -185,6 +185,10 @@ int ft_hmem_free_host(enum fi_hmem_iface iface, void *buf) return hmem_ops[iface].free_host(buf); } +/* + * Matches the behavior of memset where value is an int but + * used as a unsigned char + */ int ft_hmem_memset(enum fi_hmem_iface iface, uint64_t device, void *buf, int value, size_t size) { diff --git a/fabtests/common/hmem_ze.c b/fabtests/common/hmem_ze.c index 507470f06d1..305c58ff57d 100644 --- a/fabtests/common/hmem_ze.c +++ b/fabtests/common/hmem_ze.c @@ -382,6 +382,7 @@ int ft_ze_free(void *buf) int ft_ze_memset(uint64_t device, void *buf, int value, size_t size) { + unsigned char set_value = (unsigned char) value; ze_result_t ze_ret; ze_ret = (*libze_ops.zeCommandListReset)(cmd_list); @@ -389,7 +390,8 @@ int ft_ze_memset(uint64_t device, void *buf, int value, size_t size) return -FI_EINVAL; ze_ret = (*libze_ops.zeCommandListAppendMemoryFill)( - cmd_list, buf, &value, sizeof(value), + cmd_list, buf, &set_value, + sizeof(set_value), size, NULL, 0, NULL); if (ze_ret) return -FI_EINVAL; diff --git a/fabtests/ubertest/ofi_atomic.c b/fabtests/common/ofi_atomic.c similarity index 95% rename from fabtests/ubertest/ofi_atomic.c rename to fabtests/common/ofi_atomic.c index 311747175d5..cf006538904 100644 --- a/fabtests/ubertest/ofi_atomic.c +++ b/fabtests/common/ofi_atomic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 Intel Corporation. All rights reserved. + * Copyright (c) Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -124,24 +124,14 @@ static void ofi_read_## op ##_## type \ (void *dst, const void *src, void *res, size_t cnt) \ { \ - size_t i; \ - type *d = (dst); \ - type *r = (res); \ - OFI_UNUSED(src); \ - for (i = 0; i < cnt; i++) \ - r[i] = d[i]; \ + memcpy(res, dst, sizeof(type) * cnt); \ } #define OFI_DEF_READ_COMPLEX_FUNC(op, type) \ static void ofi_read_## op ##_## type \ (void *dst, const void *src, void *res, size_t cnt) \ { \ - size_t i; \ - ofi_complex_##type *d = (dst); \ - ofi_complex_##type *r = (res); \ - OFI_UNUSED(src); \ - for (i = 0; i < cnt; i++) \ - r[i] = d[i]; \ + memcpy(res, dst, sizeof(ofi_complex_##type) * cnt); \ } /* @@ -157,11 +147,9 @@ size_t i; \ type *d = (dst); \ const type *s = (src); \ - type *r = (res); \ - for (i = 0; i < cnt; i++) { \ - r[i] = d[i]; \ + memcpy(res, dst, sizeof(type) * cnt); \ + for (i = 0; i < cnt; i++) \ op(type, d[i], s[i]); \ - } \ } #define OFI_DEF_READWRITE_COMPLEX_FUNC(op, type) \ @@ -171,11 +159,9 @@ size_t i; \ ofi_complex_##type *d = (dst); \ const ofi_complex_##type *s = (src); \ - ofi_complex_##type *r = (res); \ - for (i = 0; i < cnt; i++) { \ - r[i] = d[i]; \ + memcpy(res, dst, sizeof(ofi_complex_##type) * cnt); \ + for (i = 0; i < cnt; i++) \ op(type, d[i], s[i]); \ - } \ } /* @@ -193,11 +179,9 @@ type *d = (dst); \ const type *s = (src); \ const type *c = (cmp); \ - type *r = (res); \ - for (i = 0; i < cnt; i++) { \ - r[i] = d[i]; \ + memcpy(res, dst, sizeof(type) * cnt); \ + for (i = 0; i < cnt; i++) \ op(type, d[i], s[i], c[i]); \ - } \ } #define OFI_DEF_CSWAP_COMPLEX_FUNC(op, type) \ @@ -209,11 +193,9 @@ ofi_complex_##type *d = (dst); \ const ofi_complex_##type *s = (src); \ const ofi_complex_##type *c = (cmp); \ - ofi_complex_##type *r = (res); \ - for (i = 0; i < cnt; i++) { \ - r[i] = d[i]; \ + memcpy(res, dst, sizeof(ofi_complex_##type) * cnt); \ + for (i = 0; i < cnt; i++) \ op(type, d[i], s[i], c[i]); \ - } \ } diff --git a/fabtests/common/shared.c b/fabtests/common/shared.c index eb95127b6f0..f5d3a70da6d 100644 --- a/fabtests/common/shared.c +++ b/fabtests/common/shared.c @@ -90,7 +90,7 @@ char *buf = NULL, *tx_buf, *rx_buf; * dev_host_buf are used by ft_fill_buf() to stage data sent over wire, * when tx_buf is on device memory. */ -void *dev_host_buf = NULL; +void *dev_host_buf = NULL, *dev_host_comp = NULL, *dev_host_res = NULL; char **tx_mr_bufs = NULL, **rx_mr_bufs = NULL; size_t buf_size, tx_buf_size, rx_buf_size; @@ -161,10 +161,6 @@ struct test_size_param *test_size = def_test_sizes; /* range of messages is dynamically allocated */ struct test_size_param *user_test_sizes; -static const char integ_alphabet[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; -static const int integ_alphabet_length = (sizeof(integ_alphabet)/sizeof(*integ_alphabet)) - 1; - - int ft_poll_fd(int fd, int timeout) { struct pollfd fds; @@ -550,14 +546,30 @@ static void ft_set_tx_rx_sizes(size_t *set_tx, size_t *set_rx) *set_tx += ft_tx_prefix_size(); } -void ft_free_host_tx_buf(void) +void ft_free_host_bufs(void) { int ret; - ret = ft_hmem_free_host(opts.iface, dev_host_buf); - if (ret) - FT_PRINTERR("ft_hmem_free_host", ret); - dev_host_buf = NULL; + if (dev_host_buf) { + ret = ft_hmem_free_host(opts.iface, dev_host_buf); + if (ret) + FT_PRINTERR("ft_hmem_free_host", ret); + dev_host_buf = NULL; + } + + if (dev_host_res) { + ret = ft_hmem_free_host(opts.iface, dev_host_res); + if (ret) + FT_PRINTERR("ft_hmem_free_host", ret); + dev_host_res = NULL; + } + + if (dev_host_comp) { + ret = ft_hmem_free_host(opts.iface, dev_host_comp); + if (ret) + FT_PRINTERR("ft_hmem_free_host", ret); + dev_host_comp = NULL; + } } /* @@ -645,6 +657,18 @@ int ft_alloc_msgs(void) max_msg_size * opts.window_size); if (ret) return ret; + + if (fi->caps & FI_ATOMIC) { + ret = ft_hmem_alloc_host(opts.iface, &dev_host_comp, + buf_size); + if (ret) + return ret; + + ret = ft_hmem_alloc_host(opts.iface, &dev_host_res, + buf_size); + if (ret) + return ret; + } } ret = ft_hmem_memset(opts.iface, opts.device, (void *) buf, 0, buf_size); @@ -1910,8 +1934,7 @@ void ft_free_res(void) buf = rx_buf = tx_buf = NULL; buf_size = rx_size = tx_size = tx_mr_size = rx_mr_size = 0; } - if (dev_host_buf) - ft_free_host_tx_buf(); + ft_free_host_bufs(); if (fi_pep) { fi_freeinfo(fi_pep); @@ -2441,18 +2464,18 @@ ssize_t ft_post_atomic(enum ft_atomic_opcodes opcode, struct fid_ep *ep, switch (opcode) { case FT_ATOMIC_BASE: FT_POST(fi_atomic, ft_progress, txcq, tx_seq, &tx_cq_cntr, - "fi_atomic", ep, buf, count, mr_desc, remote_fi_addr, + "fi_atomic", ep, tx_buf, count, mr_desc, remote_fi_addr, remote->addr, remote->key, datatype, atomic_op, context); break; case FT_ATOMIC_FETCH: FT_POST(fi_fetch_atomic, ft_progress, txcq, tx_seq, &tx_cq_cntr, - "fi_fetch_atomic", ep, buf, count, mr_desc, result, + "fi_fetch_atomic", ep, tx_buf, count, mr_desc, result, result_desc, remote_fi_addr, remote->addr, remote->key, datatype, atomic_op, context); break; case FT_ATOMIC_COMPARE: FT_POST(fi_compare_atomic, ft_progress, txcq, tx_seq, - &tx_cq_cntr, "fi_compare_atomic", ep, buf, count, + &tx_cq_cntr, "fi_compare_atomic", ep, tx_buf, count, mr_desc, compare, compare_desc, result, result_desc, remote_fi_addr, remote->addr, remote->key, datatype, atomic_op, context); @@ -3051,7 +3074,7 @@ int ft_sync_inband(bool repost_rx) int ret; if (opts.dst_addr) { - ret = ft_tx_msg(ep, remote_fi_addr, tx_buf, 1, &tx_ctx, + ret = ft_tx_msg(ep, remote_fi_addr, tx_buf, 0, &tx_ctx, FI_DELIVERY_COMPLETE); if (ret) return ret; @@ -3064,7 +3087,7 @@ int ft_sync_inband(bool repost_rx) if (ret) return ret; - ret = ft_tx_msg(ep, remote_fi_addr, tx_buf, 1, &tx_ctx, + ret = ft_tx_msg(ep, remote_fi_addr, tx_buf, 0, &tx_ctx, FI_DELIVERY_COMPLETE); if (ret) return ret; @@ -3731,6 +3754,135 @@ int ft_fill_buf(void *buf, size_t size) return ret; } +int ft_fill_atomic(void *buf, size_t count, enum fi_datatype datatype) +{ + void *fill_buf; + int ret = 0; + + if (opts.iface != FI_HMEM_SYSTEM) { + assert(dev_host_buf); + fill_buf = dev_host_buf; + } else { + fill_buf = buf; + } + + SWITCH_TYPES(datatype, FT_FILL, fill_buf, count); + + if (opts.iface != FI_HMEM_SYSTEM) { + ret = ft_hmem_copy_to(opts.iface, opts.device, buf, fill_buf, + count * datatype_to_size(datatype)); + if (ret) + FT_ERR("Failed to fill atomic buffer\n"); + } + return ret; +} + +int ft_check_atomic(enum ft_atomic_opcodes atomic, enum fi_op op, + enum fi_datatype type, void *src, void *dst_cpy, void *dst, + void *cmp, void *res, size_t count) +{ + int ret = 0; + void *check_res = res, *check_buf, *check_comp; + + /* + * If we don't have the test function, return > 0 to indicate + * verification is unsupported. + */ + if (atomic == FT_ATOMIC_COMPARE) { + if (!ofi_atomic_swap_handler(op, type)) + return 1; + } else if (atomic == FT_ATOMIC_FETCH) { + if (!ofi_atomic_readwrite_handler(op, type)) + return 1; + } else { + if (!ofi_atomic_write_handler(op, type)) + return 1; + } + + if (atomic == FT_ATOMIC_COMPARE || atomic == FT_ATOMIC_FETCH) { + if (opts.iface != FI_HMEM_SYSTEM) { + assert(dev_host_res); + ret = ft_hmem_copy_from(opts.iface, opts.device, + dev_host_res, res, + count * datatype_to_size(type)); + if (ret) { + FT_ERR("Failed to copy from atomic buffer\n"); + return ret; + } + + check_res = dev_host_res; + } else { + check_res = res; + } + if (memcmp(dst_cpy, check_res, datatype_to_size(type) * count)) { + printf("Data check error on atomic fetch buffer\n"); + return -1; + } + } + + if (atomic == FT_ATOMIC_COMPARE) { + if (opts.iface != FI_HMEM_SYSTEM) { + assert(dev_host_comp); + ret = ft_hmem_copy_from(opts.iface, opts.device, + dev_host_comp, cmp, + count * datatype_to_size(type)); + if (ret) { + FT_ERR("Failed to copy from atomic buffer\n"); + return ret; + } + check_comp = dev_host_comp; + } else { + check_comp = cmp; + } + } + + if (opts.iface != FI_HMEM_SYSTEM) { + assert(dev_host_buf); + ret = ft_hmem_copy_from(opts.iface, opts.device, dev_host_buf, + src, count * datatype_to_size(type)); + if (ret) { + FT_ERR("Failed to copy from atomic buffer\n"); + return ret; + } + + check_buf = dev_host_buf; + + } else { + check_buf = src; + } + + if (atomic == FT_ATOMIC_COMPARE) { + ofi_atomic_swap_op(op, type, dst_cpy, check_buf, check_comp, + check_res, count); + } else if (atomic == FT_ATOMIC_FETCH) { + ofi_atomic_readwrite_op(op, type, dst_cpy, check_buf, + check_res, count); + } else { + ofi_atomic_write_op(op, type, dst_cpy, check_buf, count); + } + + if (opts.iface != FI_HMEM_SYSTEM) { + ret = ft_hmem_copy_from(opts.iface, opts.device, + dev_host_buf, dst, + count * datatype_to_size(type)); + if (ret) { + FT_ERR("Failed to copy from atomic buffer\n"); + return ret; + } + + check_buf = dev_host_buf; + } else { + check_buf = dst; + } + + if (memcmp(dst_cpy, check_buf, datatype_to_size(type) * count)) { + printf("Data check error on atomic target buffer\n"); + return -1; + } + + return FI_SUCCESS; +} + int ft_check_buf(void *buf, size_t size) { char *recv_data; diff --git a/fabtests/functional/rdm_atomic.c b/fabtests/functional/rdm_atomic.c index cef31ecb229..8f4b2c88123 100644 --- a/fabtests/functional/rdm_atomic.c +++ b/fabtests/functional/rdm_atomic.c @@ -40,13 +40,13 @@ static enum fi_op op_type = FI_MIN; static void *result; static void *compare; +static void *cpy_dst; static struct fid_mr *mr_result; static struct fid_mr *mr_compare; static struct fi_context fi_ctx_atomic; static enum fi_datatype datatype; -static size_t *count; static int run_all_ops = 1, run_all_datatypes = 1; static enum fi_op get_fi_op(char *op) @@ -150,90 +150,12 @@ static void print_opts_usage(char *name) FT_PRINT_OPTS_USAGE("", "long_double|long_double_complex (default: all)"); } -#define create_atomic_op_executor(type) \ -static inline int execute_atomic_ ## type ## _op(enum fi_op op_type, \ - enum fi_datatype datatype) \ -{ \ - int ret = FI_SUCCESS, len, i; \ - len = snprintf((test_name), sizeof(test_name), "%s_", \ - fi_tostr(&(datatype), FI_TYPE_ATOMIC_TYPE)); \ - snprintf((test_name) + len, sizeof(test_name) - len, "%s_"#type"_lat", \ - fi_tostr(&op_type, FI_TYPE_ATOMIC_OP)); \ - opts.transfer_size = datatype_to_size(datatype); \ - \ - ft_start(); \ - for (i = 0; i < opts.iterations; i++) { \ - ret = execute_ ## type ## _atomic_op(op_type); \ - if (ret) \ - break; \ - } \ - ft_stop(); \ - report_perf(); \ - \ - return ret; \ -} - -#define create_atomic_op_handler(type) \ -create_atomic_op_executor(type) \ -static inline int handle_atomic_ ## type ## _op(int run_all_datatypes, \ - enum fi_op op_type, \ - size_t *count) \ -{ \ - int ret = FI_SUCCESS; \ - \ - if (run_all_datatypes) { \ - for (datatype = 0; datatype < OFI_DATATYPE_CNT; datatype++) { \ - ret = check_ ## type ## _atomic_op(ep, op_type, \ - datatype, count); \ - if (ret == -FI_ENOSYS || ret == -FI_EOPNOTSUPP) { \ - fprintf(stderr, \ - "Provider doesn't support %s ", \ - fi_tostr(&op_type, \ - FI_TYPE_ATOMIC_OP)); \ - fprintf(stderr, \ - #type" atomic operation on %s\n", \ - fi_tostr(&datatype, \ - FI_TYPE_ATOMIC_TYPE)); \ - continue; \ - } else if (ret) { \ - goto fn; \ - } \ - \ - ret = execute_atomic_ ##type ## _op(op_type, datatype); \ - if (ret) \ - goto fn; \ - } \ - } else { \ - ret = check_ ## type ## _atomic_op(ep, op_type, \ - datatype, count); \ - if (ret == -FI_ENOSYS || ret == -FI_EOPNOTSUPP) { \ - fprintf(stderr, \ - "Provider doesn't support %s ", \ - fi_tostr(&op_type, \ - FI_TYPE_ATOMIC_OP)); \ - fprintf(stderr, \ - #type" atomic operation on %s\n", \ - fi_tostr(&datatype, \ - FI_TYPE_ATOMIC_TYPE)); \ - goto fn; \ - } else if (ret) { \ - goto fn; \ - } \ - \ - ret = execute_atomic_ ## type ##_op(op_type, datatype); \ - } \ - \ -fn: \ - return ret; \ -} - - -static inline int execute_base_atomic_op(enum fi_op op) +static inline int execute_base_atomic_op(void) { int ret; ret = ft_post_atomic(FT_ATOMIC_BASE, ep, NULL, NULL, NULL, NULL, - &remote, datatype, op, &fi_ctx_atomic); + &remote, datatype, op_type, &fi_ctx_atomic); if (ret) return ret; @@ -242,13 +164,13 @@ static inline int execute_base_atomic_op(enum fi_op op) return ret; } -static inline int execute_fetch_atomic_op(enum fi_op op) +static inline int execute_fetch_atomic_op(void) { int ret; ret = ft_post_atomic(FT_ATOMIC_FETCH, ep, NULL, NULL, result, fi_mr_desc(mr_result), &remote, datatype, - op, &fi_ctx_atomic); + op_type, &fi_ctx_atomic); if (ret) return ret; @@ -257,13 +179,13 @@ static inline int execute_fetch_atomic_op(enum fi_op op) return ret; } -static inline int execute_compare_atomic_op(enum fi_op op) +static inline int execute_compare_atomic_op(void) { int ret; ret = ft_post_atomic(FT_ATOMIC_COMPARE, ep, compare, fi_mr_desc(mr_compare), result, fi_mr_desc(mr_result), &remote, datatype, - op, &fi_ctx_atomic); + op_type, &fi_ctx_atomic); if (ret) return ret; @@ -272,8 +194,44 @@ static inline int execute_compare_atomic_op(enum fi_op op) return ret; } +static int fill_data(enum ft_atomic_opcodes opcode) +{ + int ret; + + switch (opcode) { + case FT_ATOMIC_COMPARE: + ft_fill_atomic(compare, 1, datatype); + /* fall through */ + case FT_ATOMIC_FETCH: + ft_hmem_memset(opts.iface, opts.device, result, 0, + datatype_to_size(datatype)); + /* fall through */ + case FT_ATOMIC_BASE: + ft_fill_atomic(tx_buf, 1, datatype); + ft_fill_atomic(rx_buf, 1, datatype); + break; + default: + break; + } + + ret = ft_hmem_copy_from(opts.iface, opts.device, cpy_dst, + rx_buf, datatype_to_size(datatype)); + if (ret) + return ret; + + ft_sync(); + return ret; +} + static void report_perf(void) { + int len; + + len = snprintf((test_name), sizeof(test_name), "%s_", + fi_tostr(&(datatype), FI_TYPE_ATOMIC_TYPE)); + snprintf((test_name) + len, sizeof(test_name) - len, "%s_lat", + fi_tostr(&op_type, FI_TYPE_ATOMIC_OP)); + if (opts.machr) show_perf_mr(opts.transfer_size, opts.iterations, &start, &end, 1, opts.argc, opts.argv); @@ -281,21 +239,117 @@ static void report_perf(void) show_perf(test_name, opts.transfer_size, opts.iterations, &start, &end, 1); } -create_atomic_op_handler(base) -create_atomic_op_handler(fetch) -create_atomic_op_handler(compare) +static int handle_atomic_base_op(void) +{ + int ret = FI_SUCCESS, i; + size_t count = 0; -static int run_op(void) + ret = check_base_atomic_op(ep, op_type, datatype, &count); + if (ret) + return ret; + + opts.transfer_size = datatype_to_size(datatype); + ft_start(); + for (i = 0; i < opts.iterations; i++) { + if (ft_check_opts(FT_OPT_VERIFY_DATA)) { + ret = fill_data(FT_ATOMIC_BASE); + if (ret) + return ret; + } + + ret = execute_base_atomic_op(); + if (ret) + break; + + if (ft_check_opts(FT_OPT_VERIFY_DATA)) { + ft_sync(); + ret = ft_check_atomic(FT_ATOMIC_BASE, op_type, datatype, + tx_buf, cpy_dst, rx_buf, compare, + result, 1); + if (ret) + return ret; + } + } + ft_stop(); + report_perf(); + return FI_SUCCESS; +} + +static int handle_atomic_fetch_op(void) { - int ret = -FI_EINVAL; + int ret = FI_SUCCESS, i; + size_t count = 0; + + ret = check_fetch_atomic_op(ep, op_type, datatype, &count); + if (ret) + return ret; - count = (size_t *)malloc(sizeof(*count)); - if (!count) { - ret = -FI_ENOMEM; - perror("malloc"); - goto fn; + opts.transfer_size = datatype_to_size(datatype); + ft_start(); + for (i = 0; i < opts.iterations; i++) { + if (ft_check_opts(FT_OPT_VERIFY_DATA)) { + ret = fill_data(FT_ATOMIC_FETCH); + if (ret) + return ret; + } + + ret = execute_fetch_atomic_op(); + if (ret) + break; + + if (ft_check_opts(FT_OPT_VERIFY_DATA)) { + ft_sync(); + ret = ft_check_atomic(FT_ATOMIC_FETCH, op_type, datatype, + tx_buf, cpy_dst, rx_buf, compare, + result, 1); + if (ret) + return ret; + } } - ft_sync(); + ft_stop(); + report_perf(); + return FI_SUCCESS; +} + +static int handle_atomic_compare_op(void) +{ + int ret = FI_SUCCESS, i; + size_t count = 0; + + ret = check_compare_atomic_op(ep, op_type, datatype, &count); + if (ret) + return ret; + + opts.transfer_size = datatype_to_size(datatype); + ft_start(); + for (i = 0; i < opts.iterations; i++) { + if (ft_check_opts(FT_OPT_VERIFY_DATA)) { + ret = fill_data(FT_ATOMIC_COMPARE); + if (ret) + return ret; + } + + ret = execute_compare_atomic_op(); + if (ret) + break; + + if (ft_check_opts(FT_OPT_VERIFY_DATA)) { + ft_sync(); + ret = ft_check_atomic(FT_ATOMIC_COMPARE, op_type, datatype, + tx_buf, cpy_dst, rx_buf, compare, + result, 1); + if (ret) + return ret; + } + } + ft_stop(); + report_perf(); + return FI_SUCCESS; +} + +static int run_dt(void) +{ + int ret = -FI_EINVAL; switch (op_type) { case FI_MIN: @@ -309,12 +363,10 @@ static int run_op(void) case FI_LXOR: case FI_BXOR: case FI_ATOMIC_WRITE: - ret = handle_atomic_base_op(run_all_datatypes, - op_type, count); + ret = handle_atomic_base_op(); break; case FI_ATOMIC_READ: - ret = handle_atomic_fetch_op(run_all_datatypes, - op_type, count); + ret = handle_atomic_fetch_op(); break; case FI_CSWAP: case FI_CSWAP_NE: @@ -323,39 +375,58 @@ static int run_op(void) case FI_CSWAP_GE: case FI_CSWAP_GT: case FI_MSWAP: - ret = handle_atomic_compare_op(run_all_datatypes, - op_type, count); + ret = handle_atomic_compare_op(); break; default: FT_WARN("Invalid atomic operation type %d\n", op_type); break; } - ft_sync(); - free(count); -fn: + + if (ret == -FI_ENOSYS || ret == -FI_EOPNOTSUPP) { + fprintf(stderr, "Provider doesn't support %s ", + fi_tostr(&op_type, FI_TYPE_ATOMIC_OP)); + fprintf(stderr, "atomic operation on %s\n", + fi_tostr(&datatype, FI_TYPE_ATOMIC_TYPE)); + return FI_SUCCESS; + } return ret; } -static int run_ops(void) +static int run_op(void) { int ret; - for (op_type = FI_MIN; op_type < OFI_ATOMIC_OP_CNT; op_type++) { - ret = run_op(); + if (!run_all_datatypes) + return run_dt(); + + for (datatype = 0; datatype < OFI_DATATYPE_CNT; datatype++) { + ret = run_dt(); if (ret && ret != -FI_ENOSYS && ret != -FI_EOPNOTSUPP) { FT_PRINTERR("run_op", ret); return ret; } } - - return 0; + return FI_SUCCESS; } static int run_test(void) { - return run_all_ops ? run_ops() : run_op(); + int ret; + + if (!run_all_ops) + return run_op(); + + for (op_type = FI_MIN; op_type < OFI_ATOMIC_OP_CNT; op_type++) { + ret = run_op(); + if (ret && ret != -FI_ENOSYS && ret != -FI_EOPNOTSUPP) { + FT_PRINTERR("run_op", ret); + return ret; + } + } + + return FI_SUCCESS; } static void free_res(void) @@ -370,6 +441,10 @@ static void free_res(void) ft_hmem_free(opts.iface, compare); compare = NULL; } + if (cpy_dst) { + ft_hmem_free_host(opts.iface, cpy_dst); + cpy_dst = NULL; + } } static uint64_t get_mr_key() @@ -396,6 +471,10 @@ static int alloc_ep_res(struct fi_info *fi) return -1; } + ret = ft_hmem_alloc_host(opts.iface, &cpy_dst, opts.transfer_size); + if (ret) + return ret; + // registers local data buffer that stores results ret = ft_reg_mr(fi, result, buf_size, (mr_local ? FI_READ : 0) | FI_REMOTE_WRITE, @@ -453,7 +532,7 @@ int main(int argc, char **argv) if (!hints) return EXIT_FAILURE; - while ((op = getopt_long(argc, argv, "ho:Uz:" CS_OPTS INFO_OPTS, + while ((op = getopt_long(argc, argv, "ho:Uz:v" CS_OPTS INFO_OPTS, long_opts, &lopt_idx)) != -1) { switch (op) { case 'o': @@ -483,6 +562,9 @@ int main(int argc, char **argv) } } break; + case 'v': + opts.options |= FT_OPT_VERIFY_DATA; + break; default: if (!ft_parse_long_opts(op, optarg)) continue; diff --git a/fabtests/ubertest/ofi_atomic.h b/fabtests/include/ofi_atomic.h similarity index 72% rename from fabtests/ubertest/ofi_atomic.h rename to fabtests/include/ofi_atomic.h index a61a7bae432..765a4a8137f 100644 --- a/fabtests/ubertest/ofi_atomic.h +++ b/fabtests/include/ofi_atomic.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Intel Corporation. All rights reserved. + * Copyright (c) Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -33,16 +33,14 @@ #ifndef _OFI_ATOMIC_H_ #define _OFI_ATOMIC_H_ -#include "fabtest.h" +#include "shared.h" +#include "ft_osd.h" #ifdef __cplusplus extern "C" { #endif typedef long double long_double; -typedef float complex ofi_complex_float; -typedef double complex ofi_complex_double; -typedef long double complex ofi_complex_long_double; #define OFI_WRITE_OP_START FI_MIN #define OFI_WRITE_OP_LAST (FI_ATOMIC_WRITE + 1) @@ -83,42 +81,6 @@ extern void (*ofi_atomic_swap_handlers[OFI_SWAP_OP_CNT][OFI_DATATYPE_CNT]) #define ofi_atomic_swap_op(op, datatype, dst, src, cmp, res, cnt) \ ofi_atomic_swap_handler(op, datatype)(dst, src, cmp, res, cnt) -#define OFI_DEF_COMPLEX_OPS(type) \ -static inline int ofi_complex_eq_## type \ - (ofi_complex_## type a, ofi_complex_## type b) \ -{ \ - return a == b; \ -} \ -static inline ofi_complex_## type ofi_complex_sum_## type \ - (ofi_complex_## type a, ofi_complex_## type b) \ -{ \ - return a + b; \ -} \ -static inline ofi_complex_## type ofi_complex_prod_## type \ - (ofi_complex_## type a, ofi_complex_## type b) \ -{ \ - return a * b; \ -} \ -static inline ofi_complex_## type ofi_complex_land_## type \ - (ofi_complex_## type a, ofi_complex_## type b) \ -{ \ - return a && b; \ -} \ -static inline ofi_complex_## type ofi_complex_lor_## type \ - (ofi_complex_## type a, ofi_complex_## type b) \ -{ \ - return a || b; \ -} \ -static inline int ofi_complex_lxor_## type \ - (ofi_complex_## type a, ofi_complex_## type b) \ -{ \ - return (a && !b) || (!a && b); \ -} \ - -OFI_DEF_COMPLEX_OPS(float) -OFI_DEF_COMPLEX_OPS(double) -OFI_DEF_COMPLEX_OPS(long_double) - #ifdef __cplusplus } #endif diff --git a/fabtests/include/shared.h b/fabtests/include/shared.h index 7d56fdd7257..67a881a91e1 100644 --- a/fabtests/include/shared.h +++ b/fabtests/include/shared.h @@ -43,11 +43,14 @@ #include #include #include +#include #include #include #include +#include "ofi_atomic.h" + #ifdef __cplusplus extern "C" { #endif @@ -276,7 +279,11 @@ void ft_mcusage(char *name, char *desc); void ft_csusage(char *name, char *desc); int ft_fill_buf(void *buf, size_t size); +int ft_fill_atomic(void *buf, size_t count, enum fi_datatype datatype); int ft_check_buf(void *buf, size_t size); +int ft_check_atomic(enum ft_atomic_opcodes atomic, enum fi_op op, + enum fi_datatype type, void *src, void *orig_dst, void *dst, + void *cmp, void *res, size_t count); int ft_check_opts(uint64_t flags); uint64_t ft_init_cq_data(struct fi_info *info); int ft_sock_listen(char *node, char *service); @@ -451,8 +458,8 @@ int ft_alloc_ep_res(struct fi_info *fi, struct fid_cq **new_txcq, struct fid_cntr **new_rma_cntr, struct fid_av **new_av); int ft_alloc_msgs(void); -int ft_alloc_host_tx_buf(size_t size); -void ft_free_host_tx_buf(void); +int ft_alloc_host_bufs(size_t size); +void ft_free_host_bufs(void); int ft_alloc_active_res(struct fi_info *fi); int ft_enable_ep_recv(void); int ft_enable_ep(struct fid_ep *bind_ep, struct fid_eq *bind_eq, struct fid_av *bind_av, @@ -745,4 +752,58 @@ static inline void *ft_get_page_end(const void *addr, size_t page_size) + page_size, page_size) - 1); } +/* + * Common validation functions and variables + */ + +#define integ_alphabet "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define integ_alphabet_length (sizeof(integ_alphabet) - 1) + +#define FT_FILL(dst,cnt,TYPE) \ + do { \ + int i, a = 0; \ + TYPE *d = (dst); \ + for (i = 0; i < cnt; i++) { \ + memcpy(&d[i], &integ_alphabet[a], sizeof(TYPE)); \ + if (++a >= integ_alphabet_length) \ + a = 0; \ + } \ + } while (0); + +#ifdef HAVE___INT128 + +/* If __int128 supported, things just work. */ +#define FT_FILL_INT128(...) FT_FILL(__VA_ARGS__) + +#else + +/* If __int128, we're not going to fill/verify. */ +#define FT_FILL_INT128(...) + +#endif + +#define EXPAND( x ) x + +#define SWITCH_TYPES(type,FUNC,...) \ + switch (type) { \ + case FI_INT8: EXPAND( FUNC(__VA_ARGS__,int8_t) ); break; \ + case FI_UINT8: EXPAND( FUNC(__VA_ARGS__,uint8_t) ); break; \ + case FI_INT16: EXPAND( FUNC(__VA_ARGS__,int16_t) ); break; \ + case FI_UINT16: EXPAND( FUNC(__VA_ARGS__,uint16_t) ); break; \ + case FI_INT32: EXPAND( FUNC(__VA_ARGS__,int32_t) ); break; \ + case FI_UINT32: EXPAND( FUNC(__VA_ARGS__,uint32_t) ); break; \ + case FI_INT64: EXPAND( FUNC(__VA_ARGS__,int64_t) ); break; \ + case FI_UINT64: EXPAND( FUNC(__VA_ARGS__,uint64_t) ); break; \ + case FI_INT128: EXPAND( FUNC##_INT128(__VA_ARGS__,ofi_int128_t) ); break; \ + case FI_UINT128: EXPAND( FUNC##_INT128(__VA_ARGS__,ofi_uint128_t) ); break; \ + case FI_FLOAT: EXPAND( FUNC(__VA_ARGS__,float) ); break; \ + case FI_DOUBLE: EXPAND( FUNC(__VA_ARGS__,double) ); break; \ + case FI_LONG_DOUBLE: EXPAND( FUNC(__VA_ARGS__,long double) ); break; \ + case FI_FLOAT_COMPLEX: EXPAND( FUNC(__VA_ARGS__,ofi_complex_float) ); break; \ + case FI_DOUBLE_COMPLEX: EXPAND( FUNC(__VA_ARGS__,ofi_complex_double) ); break; \ + case FI_LONG_DOUBLE_COMPLEX: EXPAND( FUNC(__VA_ARGS__,ofi_complex_long_double) ); break;\ + default: return -FI_EOPNOTSUPP; \ + } + + #endif /* _SHARED_H_ */ diff --git a/fabtests/include/unix/osd.h b/fabtests/include/unix/osd.h index ec8ca1020fb..bc46bafba62 100644 --- a/fabtests/include/unix/osd.h +++ b/fabtests/include/unix/osd.h @@ -84,8 +84,8 @@ static inline int ofi_sockerr(void) } /* complex operations implementation */ -#define OFI_COMPLEX(name) ofi_##name##_complex -#define OFI_COMPLEX_OP(name, op) ofi_complex_##name##_##op +#define OFI_COMPLEX(name) ofi_complex_##name +#define OFI_COMPLEX_OP(name, op) ofi_complex_##op##_##name #define OFI_COMPLEX_TYPE_DECL(name, type) typedef type complex OFI_COMPLEX(name); OFI_COMPLEX_TYPE_DECL(float, float) @@ -97,11 +97,11 @@ static inline OFI_COMPLEX(name) OFI_COMPLEX_OP(name, sum)(OFI_COMPLEX(name) v1, { \ return v1 + v2; \ } \ -static inline OFI_COMPLEX(name) OFI_COMPLEX_OP(name, mul)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2) \ +static inline OFI_COMPLEX(name) OFI_COMPLEX_OP(name, prod)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2) \ { \ return v1 * v2; \ } \ -static inline int OFI_COMPLEX_OP(name, equ)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2) \ +static inline int OFI_COMPLEX_OP(name, eq)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2) \ { \ return v1 == v2; \ } \ @@ -112,7 +112,11 @@ static inline OFI_COMPLEX(name) OFI_COMPLEX_OP(name, land)(OFI_COMPLEX(name) v1, static inline OFI_COMPLEX(name) OFI_COMPLEX_OP(name, lor)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2) \ { \ return v1 || v2; \ -} +} \ +static inline OFI_COMPLEX(name) OFI_COMPLEX_OP(name, lxor)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2)\ +{ \ + return (v1 && !v2) || (!v1 && v2); \ +} \ OFI_COMPLEX_OPS(float) OFI_COMPLEX_OPS(double) diff --git a/fabtests/include/windows/osd.h b/fabtests/include/windows/osd.h index 564f4453c16..644ca768667 100644 --- a/fabtests/include/windows/osd.h +++ b/fabtests/include/windows/osd.h @@ -726,9 +726,9 @@ ofi_send_socket(SOCKET fd, const void *buf, size_t count, int flags) /* complex operations implementation */ -#define OFI_COMPLEX(name) ofi_##name##_complex +#define OFI_COMPLEX(name) ofi_complex_##name #define OFI_COMPLEX_BASE(name) OFI_COMPLEX(name)##_base -#define OFI_COMPLEX_OP(name, op) ofi_complex_##name##_##op +#define OFI_COMPLEX_OP(name, op) ofi_complex_##op##_##name #define OFI_COMPLEX_TYPE_DECL(name, type) \ typedef type OFI_COMPLEX_BASE(name); \ typedef struct { \ @@ -754,30 +754,37 @@ static inline OFI_COMPLEX(name) OFI_COMPLEX_OP(name, sum)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) ret = {.re = v1.re + v2.re, .im = v1.im + v2.im}; \ return ret; \ } \ -static inline OFI_COMPLEX(name) OFI_COMPLEX_OP(name, mul)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2) \ +static inline OFI_COMPLEX(name) OFI_COMPLEX_OP(name, prod)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2) \ { \ OFI_COMPLEX(name) ret = {.re = (v1.re * v2.re) - (v1.im * v2.im), \ .im = (v1.re * v2.im) + (v1.im * v2.re)}; \ return ret; \ } \ -static inline int OFI_COMPLEX_OP(name, equ)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2) \ +static inline int OFI_COMPLEX_OP(name, eq)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2) \ { \ return v1.re == v2.re && v1.im == v2.im; \ } \ static inline OFI_COMPLEX(name) OFI_COMPLEX_OP(name, land)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2) \ { \ OFI_COMPLEX(name) zero = {.re = 0, .im = 0}; \ - int equ = !OFI_COMPLEX_OP(name, equ)(v1, zero) && !OFI_COMPLEX_OP(name, equ)(v2, zero); \ + int equ = !OFI_COMPLEX_OP(name, eq)(v1, zero) && !OFI_COMPLEX_OP(name, eq)(v2, zero); \ + OFI_COMPLEX(name) ret = {.re = equ ? 1.f : 0, .im = 0}; \ + return ret; \ +} \ +static inline OFI_COMPLEX(name) OFI_COMPLEX_OP(name, lxor)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2) \ +{ \ + OFI_COMPLEX(name) zero = {.re = 0, .im = 0}; \ + int equ = !OFI_COMPLEX_OP(name, eq)(v1, zero) && !OFI_COMPLEX_OP(name, eq)(v2, zero); \ OFI_COMPLEX(name) ret = {.re = equ ? 1.f : 0, .im = 0}; \ return ret; \ } \ static inline OFI_COMPLEX(name) OFI_COMPLEX_OP(name, lor)(OFI_COMPLEX(name) v1, OFI_COMPLEX(name) v2) \ { \ OFI_COMPLEX(name) zero = {.re = 0, .im = 0}; \ - int equ = !OFI_COMPLEX_OP(name, equ)(v1, zero) || !OFI_COMPLEX_OP(name, equ)(v2, zero); \ + int equ = !OFI_COMPLEX_OP(name, eq)(v1, zero) || !OFI_COMPLEX_OP(name, eq)(v2, zero); \ OFI_COMPLEX(name) ret = {.re = equ ? 1.f : 0, .im = 0}; \ return ret; \ -} +} \ OFI_COMPLEX_OPS(float) OFI_COMPLEX_OPS(double) diff --git a/fabtests/scripts/runfabtests.sh b/fabtests/scripts/runfabtests.sh index 8b402aa38e1..65cc9958f6f 100755 --- a/fabtests/scripts/runfabtests.sh +++ b/fabtests/scripts/runfabtests.sh @@ -173,6 +173,8 @@ short_tests=( "fi_rma_bw -e rdm -o writedata -I 5 -U" "fi_rdm_atomic -I 5 -o all" "fi_rdm_atomic -I 5 -o all -U" + "fi_rdm_atomic -I 5 -o all -v" + "fi_rdm_atomic -I 5 -o all -U -v" "fi_rdm_cntr_pingpong -I 5" "fi_multi_recv -e rdm -I 5" "fi_multi_recv -e msg -I 5" @@ -209,6 +211,8 @@ standard_tests=( "fi_rma_bw -e rdm -o writedata -U" "fi_rdm_atomic -o all -I 1000" "fi_rdm_atomic -o all -I 1000 -U" + "fi_rdm_atomic -o all -I 1000 -v" + "fi_rdm_atomic -o all -I 1000 -U -v" "fi_rdm_cntr_pingpong" "fi_multi_recv -e rdm" "fi_multi_recv -e msg" diff --git a/fabtests/ubertest/test_ctrl.c b/fabtests/ubertest/test_ctrl.c index 4b4ee462813..30b43749499 100644 --- a/fabtests/ubertest/test_ctrl.c +++ b/fabtests/ubertest/test_ctrl.c @@ -870,9 +870,9 @@ static int ft_unit_atomic(void) ft_atom_ctrl.count = ft_tx_ctrl.rma_msg_size / ft_atom_ctrl.datatype_size; if (ret == -FI_ENOSYS || ret == -FI_EOPNOTSUPP || - ft_atom_ctrl.count > count || ft_atom_ctrl.count == 0) { + ft_atom_ctrl.count > count || ft_atom_ctrl.count == 0) return 0; - } + if (ret) return ret; @@ -1018,7 +1018,7 @@ void ft_cleanup(void) FT_CLOSE_FID(ft_atom_ctrl.comp_mr); ft_cleanup_xcontrol(&ft_rx_ctrl); ft_cleanup_xcontrol(&ft_tx_ctrl); - ft_free_host_tx_buf(); + ft_free_host_bufs(); ft_cleanup_mr_control(&ft_mr_ctrl); ft_cleanup_atomic_control(&ft_atom_ctrl); ft_cleanup_random(); diff --git a/fabtests/ubertest/verify.c b/fabtests/ubertest/verify.c index 1503d9ca2e3..ebedc8d4ed7 100644 --- a/fabtests/ubertest/verify.c +++ b/fabtests/ubertest/verify.c @@ -35,79 +35,14 @@ #include "ofi_atomic.h" #include "fabtest.h" -static const char integ_alphabet[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; -static const int integ_alphabet_length = (sizeof(integ_alphabet)/sizeof(*integ_alphabet)) - 1; - -#define CHECK_LOCAL(res,local,cnt,ret,TYPE) \ - do { \ - int i; \ - TYPE *r = (res); \ - TYPE *l = (local); \ - for (i = 0; i < cnt; i++) { \ - if (r[i] != l[i]) { \ - ret = -FI_EIO; \ - break; \ - } \ - } \ - } while (0) \ - - -#define FT_FILL(dst,cnt,TYPE) \ - do { \ - int i, a = 0; \ - TYPE *d = (dst); \ - for (i = 0; i < cnt; i++) { \ - d[i] = (TYPE) (integ_alphabet[a]); \ - if (++a >= integ_alphabet_length) \ - a = 0; \ - } \ - } while (0) - -#ifdef HAVE___INT128 - -/* If __int128 supported, things just work. */ -#define FT_FILL_INT128(...) FT_FILL(__VA_ARGS__) -#define CHECK_LOCAL_INT128(...) CHECK_LOCAL(__VA_ARGS__) - -#else - -/* If __int128, we're not going to fill/verify. */ -#define FT_FILL_INT128(...) -#define CHECK_LOCAL_INT128(...) - -#endif - -#define SWITCH_TYPES(type,FUNC,...) \ - switch (type) { \ - case FI_INT8: FUNC(__VA_ARGS__,int8_t); break; \ - case FI_UINT8: FUNC(__VA_ARGS__,uint8_t); break; \ - case FI_INT16: FUNC(__VA_ARGS__,int16_t); break; \ - case FI_UINT16: FUNC(__VA_ARGS__,uint16_t); break; \ - case FI_INT32: FUNC(__VA_ARGS__,int32_t); break; \ - case FI_UINT32: FUNC(__VA_ARGS__,uint32_t); break; \ - case FI_INT64: FUNC(__VA_ARGS__,int64_t); break; \ - case FI_UINT64: FUNC(__VA_ARGS__,uint64_t); break; \ - case FI_INT128: FUNC##_INT128(__VA_ARGS__,ofi_int128_t); break; \ - case FI_UINT128: FUNC##_INT128(__VA_ARGS__,ofi_uint128_t); break; \ - case FI_FLOAT: FUNC(__VA_ARGS__,float); break; \ - case FI_DOUBLE: FUNC(__VA_ARGS__,double); break; \ - case FI_LONG_DOUBLE: FUNC(__VA_ARGS__,long_double); break; \ - case FI_FLOAT_COMPLEX: FUNC(__VA_ARGS__,ofi_complex_float); break; \ - case FI_DOUBLE_COMPLEX: FUNC(__VA_ARGS__,ofi_complex_double); break; \ - case FI_LONG_DOUBLE_COMPLEX: FUNC(__VA_ARGS__,ofi_complex_long_double); break;\ - default: return -FI_EOPNOTSUPP; \ - } - int ft_sync_fill_bufs(size_t size) { int ret; ft_sock_sync(sock, 0); if (test_info.caps & FI_ATOMIC) { - SWITCH_TYPES(ft_atom_ctrl.datatype, FT_FILL, ft_tx_ctrl.buf, - ft_atom_ctrl.count); - SWITCH_TYPES(ft_atom_ctrl.datatype, FT_FILL, ft_mr_ctrl.buf, - ft_atom_ctrl.count); + (void)ft_fill_atomic(ft_tx_ctrl.buf, ft_atom_ctrl.count, ft_atom_ctrl.datatype); + (void)ft_fill_atomic(ft_mr_ctrl.buf, ft_atom_ctrl.count, ft_atom_ctrl.datatype); memcpy(ft_atom_ctrl.orig_buf, ft_mr_ctrl.buf, size); memcpy(ft_tx_ctrl.cpy_buf, ft_tx_ctrl.buf, size); } else if (is_read_func(test_info.class_function)) { @@ -131,67 +66,26 @@ int ft_sync_fill_bufs(size_t size) return 0; } -static int verify_atomic(void) -{ - int ret = 0; - void *dst, *src, *cmp, *tmp, *res; - enum fi_datatype type; - enum fi_op op; - size_t count; - - dst = ft_atom_ctrl.orig_buf; - src = ft_tx_ctrl.cpy_buf; - - cmp = ft_atom_ctrl.comp_buf; - tmp = ft_rx_ctrl.buf; - res = ft_atom_ctrl.res_buf; - - type = ft_atom_ctrl.datatype; - op = ft_atom_ctrl.op; - count = ft_atom_ctrl.count; - - /* - * If we don't have the test function, return > 0 to indicate - * verification is unsupported. - */ - if (is_compare_func(test_info.class_function)) { - if (!ofi_atomic_swap_handler(op, type)) - return 1; - } else if (is_fetch_func(test_info.class_function)) { - if (!ofi_atomic_readwrite_handler(op, type)) - return 1; - } else { - if (!ofi_atomic_write_handler(op, type)) - return 1; - } - - if (is_fetch_func(test_info.class_function) || - is_compare_func(test_info.class_function)) { - SWITCH_TYPES(type, CHECK_LOCAL, dst, res, count, ret); - if (ret) - return ret; - } - - if (is_compare_func(test_info.class_function)) { - ofi_atomic_swap_op(op, type, dst, src, cmp, tmp, count); - } else if (is_fetch_func(test_info.class_function)) { - ofi_atomic_readwrite_op(op, type, dst, src, tmp, count); - } else { - ofi_atomic_write_op(op, type, dst, src, count); - } - - SWITCH_TYPES(type, CHECK_LOCAL, dst, ft_mr_ctrl.buf, count, ret); - - return ret; -} - int ft_verify_bufs() { char *compare_buf; size_t compare_size; + enum ft_atomic_opcodes opcode; - if (test_info.caps & FI_ATOMIC) - return verify_atomic(); + if (test_info.caps & FI_ATOMIC) { + if (is_compare_func(test_info.class_function)) + opcode = FT_ATOMIC_COMPARE; + else if (is_fetch_func(test_info.class_function)) + opcode = FT_ATOMIC_FETCH; + else + opcode = FT_ATOMIC_BASE; + + return ft_check_atomic(opcode, ft_atom_ctrl.op, + ft_atom_ctrl.datatype, ft_tx_ctrl.cpy_buf, + ft_atom_ctrl.orig_buf, ft_mr_ctrl.buf, + ft_atom_ctrl.comp_buf, ft_atom_ctrl.res_buf, + ft_atom_ctrl.count); + } if (test_info.caps & FI_RMA) { compare_size = ft_tx_ctrl.rma_msg_size; diff --git a/prov/psm3/src/psmx3_atomic.c b/prov/psm3/src/psmx3_atomic.c index da0781e654d..8c8d3400c68 100644 --- a/prov/psm3/src/psmx3_atomic.c +++ b/prov/psm3/src/psmx3_atomic.c @@ -401,12 +401,12 @@ static int psmx3_atomic_do_write(void *dest, void *src, break; case FI_LOR: - SWITCH_INT_TYPE(datatype,PSMX3_ATOMIC_WRITE, + SWITCH_ALL_TYPE(datatype,PSMX3_ATOMIC_WRITE, dest,src,count,PSMX3_LOR); break; case FI_LAND: - SWITCH_INT_TYPE(datatype,PSMX3_ATOMIC_WRITE, + SWITCH_ALL_TYPE(datatype,PSMX3_ATOMIC_WRITE, dest,src,count,PSMX3_LAND); break; @@ -421,7 +421,7 @@ static int psmx3_atomic_do_write(void *dest, void *src, break; case FI_LXOR: - SWITCH_INT_TYPE(datatype,PSMX3_ATOMIC_WRITE, + SWITCH_ALL_TYPE(datatype,PSMX3_ATOMIC_WRITE, dest,src,count,PSMX3_LXOR); break; @@ -601,7 +601,8 @@ int psmx3_am_atomic_handler(psm2_am_token_t token, if (!op_error) { addr += mr->offset; - psmx3_atomic_do_write(addr, src, datatype, op, count); + op_error = psmx3_atomic_do_write(addr, src, datatype, + op, count); if (rx->ep->caps & FI_RMA_EVENT) { cntr = rx->ep->remote_write_cntr; @@ -646,8 +647,8 @@ int psmx3_am_atomic_handler(psm2_am_token_t token, addr += mr->offset; tmp_buf = malloc(len); if (tmp_buf) - psmx3_atomic_do_readwrite(addr, src, tmp_buf, - datatype, op, count); + op_error = psmx3_atomic_do_readwrite(addr, src, + tmp_buf, datatype, op, count); else op_error = -FI_ENOMEM; @@ -698,9 +699,10 @@ int psmx3_am_atomic_handler(psm2_am_token_t token, addr += mr->offset; tmp_buf = malloc(len); if (tmp_buf) - psmx3_atomic_do_compwrite(addr, src, (uint8_t *)src + len, - tmp_buf, datatype, - op, count); + op_error = psmx3_atomic_do_compwrite(addr, src, + (uint8_t *)src + len, + tmp_buf, datatype, + op, count); else op_error = -FI_ENOMEM; @@ -2067,6 +2069,11 @@ static int psmx3_atomic_writevalid_internal(size_t chunk_size, switch (op) { case FI_MIN: case FI_MAX: + if (datatype == FI_FLOAT_COMPLEX || + datatype == FI_DOUBLE_COMPLEX || + datatype == FI_LONG_DOUBLE_COMPLEX) + return -FI_EOPNOTSUPP; + /* fall through */ case FI_SUM: case FI_PROD: case FI_LOR: @@ -2098,6 +2105,11 @@ static int psmx3_atomic_readwritevalid_internal(size_t chunk_size, switch (op) { case FI_MIN: case FI_MAX: + if (datatype == FI_FLOAT_COMPLEX || + datatype == FI_DOUBLE_COMPLEX || + datatype == FI_LONG_DOUBLE_COMPLEX) + return -FI_EOPNOTSUPP; + /* fall through */ case FI_SUM: case FI_PROD: case FI_LOR: @@ -2107,6 +2119,10 @@ static int psmx3_atomic_readwritevalid_internal(size_t chunk_size, case FI_LXOR: case FI_BXOR: case FI_ATOMIC_READ: + /* Disable failing combinations */ + if (datatype == FI_LONG_DOUBLE || + datatype == FI_LONG_DOUBLE_COMPLEX) + return -FI_EOPNOTSUPP; case FI_ATOMIC_WRITE: break; @@ -2128,6 +2144,10 @@ static int psmx3_atomic_compwritevalid_internal(size_t chunk_size, if (datatype >= OFI_DATATYPE_LAST) return -FI_EOPNOTSUPP; + /* Disable failing combinations */ + if (datatype == FI_LONG_DOUBLE || datatype == FI_LONG_DOUBLE_COMPLEX) + return -FI_EOPNOTSUPP; + switch (op) { case FI_CSWAP: case FI_CSWAP_NE: