From 299942eae0267f65599d1dc449dbe286f3eab9ac Mon Sep 17 00:00:00 2001 From: Liu Liu Date: Fri, 11 Aug 2023 19:35:28 -0400 Subject: [PATCH] Fix a hash table issue (!!!) when distance > 255. --- lib/BUILD.bazel | 1 + lib/ccv_util.c | 29 ++++++++++++------- lib/nnc/ccv_nnc_symbolic_graph_compile.c | 1 + .../ccv_nnc_symbolic_graph_memory_reduction.c | 3 +- lib/nnc/makefile | 2 +- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/lib/BUILD.bazel b/lib/BUILD.bazel index ba172f6fb..72143cf2e 100644 --- a/lib/BUILD.bazel +++ b/lib/BUILD.bazel @@ -495,6 +495,7 @@ cc_library( "nnc/ccv_nnc_symbolic_graph_simplify.c", "nnc/ccv_nnc_symbolic_graph_parallel.c", "nnc/ccv_nnc_symbolic_graph_memory_compression.c", + "nnc/ccv_nnc_symbolic_graph_memory_reduction.c", "nnc/ccv_nnc_xpu_alloc.c", "nnc/ccv_nnc_dynamic_graph.c", "nnc/ccv_nnc_dynamic_graph_alloc.c", diff --git a/lib/ccv_util.c b/lib/ccv_util.c index 8b379ac40..fbfd986f9 100644 --- a/lib/ccv_util.c +++ b/lib/ccv_util.c @@ -410,6 +410,15 @@ static uint32_t _ccv_sparse_matrix_size_for_index(const int prime_index) return _ccv_sparse_prime[prime_index - 1]; } +static uint32_t _ccv_sparse_matrix_k_from_index(const uint32_t hash, const int prime_index, const uint32_t size, const uint32_t k) +{ + uint32_t idx = _ccv_sparse_matrix_index_for_hash(hash, prime_index); + if (k > idx) + return k - idx + 2; + else + return size + k - idx + 2; +} + static void _ccv_init_sparse_matrix_vector(ccv_sparse_matrix_vector_t* vector, const ccv_sparse_matrix_t* const mat) { if (mat->type & CCV_DENSE_VECTOR) @@ -474,7 +483,7 @@ static inline void _ccv_move_sparse_matrix_vector(ccv_sparse_matrix_index_t* con } uint32_t j = index[idx].ifbit; if (j == 0xff) - j = _ccv_sparse_matrix_index_for_hash(index[idx].i + size - idx, prime_index) + 2; + j = _ccv_sparse_matrix_k_from_index(index[idx].i, prime_index, size, idx); if (k > j) { index[idx].ifbit = k > 0xff ? 0xff : k; @@ -524,7 +533,7 @@ static ccv_sparse_matrix_vector_t* _ccv_get_or_add_sparse_matrix_vector(ccv_spar idx = 0; uint32_t j = index[idx].ifbit; if (j == 0xff) - j = _ccv_sparse_matrix_index_for_hash(index[idx].i + size - idx, prime_index) + 2; + j = _ccv_sparse_matrix_k_from_index(index[idx].i, prime_index, size, idx); if (k > j) { ++mat->rnum; @@ -567,7 +576,7 @@ ccv_sparse_matrix_vector_t* ccv_get_sparse_matrix_vector(const ccv_sparse_matrix idx = 0; uint32_t j = index[idx].ifbit; if (j == 0xff) - j = _ccv_sparse_matrix_index_for_hash(index[idx].i + size - idx, prime_index) + 2; + j = _ccv_sparse_matrix_k_from_index(index[idx].i, prime_index, size, idx); if (k > j) return 0; if (index[idx].i == i) @@ -613,7 +622,7 @@ ccv_numeric_data_t ccv_get_sparse_matrix_cell_from_vector(const ccv_sparse_matri ccv_sparse_matrix_index_t* const index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx); uint32_t j = index_idx->ifbit; if (j == 0xff) - j = _ccv_sparse_matrix_index_for_hash(index_idx->i + size - idx, prime_index) + 2; + j = _ccv_sparse_matrix_k_from_index(index_idx->i, prime_index, size, idx); if (k > j) return cell; if (index_idx->i == vidx) @@ -712,7 +721,7 @@ static void _ccv_sparse_matrix_vector_inc_size(const ccv_sparse_matrix_t* const break; } if (j == 0xff) - j = _ccv_sparse_matrix_index_for_hash((index_idx->i + new_size - idx), prime_index) + 2; // This is valid because on overflow, unsigned is well defined. + j = _ccv_sparse_matrix_k_from_index(index_idx->i, prime_index, new_size, idx) + 2; // This is valid because on overflow, unsigned is well defined. if (k <= j) // j could be either a valid one or 1, in any case, this will pass. continue; index_idx->ifbit = k > 0xff ? 0xff : k; @@ -802,7 +811,7 @@ static void _ccv_sparse_matrix_inc_size(ccv_sparse_matrix_t* mat) break; } if (j == 0xff) - j = _ccv_sparse_matrix_index_for_hash((index[idx].i + new_size - idx), prime_index) + 2; // This is valid because on overflow, unsigned is well defined. + j = _ccv_sparse_matrix_k_from_index(index[idx].i, prime_index, new_size, idx); // This is valid because on overflow, unsigned is well defined. if (k <= j) // j could be either a valid one or 1, in any case, this will pass. continue; index[idx].ifbit = k > 0xff ? 0xff : k; @@ -877,7 +886,7 @@ static inline void _ccv_move_sparse_matrix_cell(uint8_t* const index, uint32_t k } uint32_t j = index_idx->ifbit; if (j == 0xff) - j = _ccv_sparse_matrix_index_for_hash(index_idx->i + size - idx, prime_index) + 2; + j = _ccv_sparse_matrix_k_from_index(index_idx->i, prime_index, size, idx); if (k > j) { index_idx->ifbit = k > 0xff ? 0xff : k; @@ -949,7 +958,7 @@ void ccv_set_sparse_matrix_cell_from_vector(ccv_sparse_matrix_t* mat, ccv_sparse ccv_sparse_matrix_index_t* const index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx); uint32_t j = index_idx->ifbit; if (j == 0xff) - j = _ccv_sparse_matrix_index_for_hash(index_idx->i + size - idx, prime_index) + 2; + j = _ccv_sparse_matrix_k_from_index(index_idx->i, prime_index, size, idx); if (k > j) { ++vector->rnum; @@ -980,7 +989,7 @@ void ccv_set_sparse_matrix_cell(ccv_sparse_matrix_t* mat, int row, int col, cons // This will handle initialize a vector if it doesn't already exist. if ((mat->rnum + 1) * 10llu > mat->size * 9llu) // expand when reached 90%. _ccv_sparse_matrix_inc_size(mat); - ccv_sparse_matrix_vector_t* const vector = _ccv_get_or_add_sparse_matrix_vector(mat, hidx); + ccv_sparse_matrix_vector_t* vector = _ccv_get_or_add_sparse_matrix_vector(mat, hidx); const size_t cell_size = CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type); if (mat->type & CCV_DENSE_VECTOR) { @@ -1032,7 +1041,7 @@ void ccv_set_sparse_matrix_cell(ccv_sparse_matrix_t* mat, int row, int col, cons ccv_sparse_matrix_index_t* const index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx); uint32_t j = index_idx->ifbit; if (j == 0xff) - j = _ccv_sparse_matrix_index_for_hash(index_idx->i + size - idx, prime_index) + 2; + j = _ccv_sparse_matrix_k_from_index(index_idx->i, prime_index, size, idx); if (k > j) { ++vector->rnum; diff --git a/lib/nnc/ccv_nnc_symbolic_graph_compile.c b/lib/nnc/ccv_nnc_symbolic_graph_compile.c index c2cedd66e..5adc378c2 100644 --- a/lib/nnc/ccv_nnc_symbolic_graph_compile.c +++ b/lib/nnc/ccv_nnc_symbolic_graph_compile.c @@ -2031,6 +2031,7 @@ static void _ccv_nnc_exec_dep_and_tensor_blocks_prep(const ccv_nnc_symbolic_grap if (buf_size > 0) { ccv_sparse_matrix_vector_t* vector = ccv_get_sparse_matrix_vector(exec_dep, outgoing); + assert(vector); for (j = 0; j < buf_size; j++) /* set with all idx's dependencies as well */ { ccv_numeric_data_t cell = ccv_get_sparse_matrix_cell_from_vector(exec_dep, vector, buf[j * 2]); diff --git a/lib/nnc/ccv_nnc_symbolic_graph_memory_reduction.c b/lib/nnc/ccv_nnc_symbolic_graph_memory_reduction.c index d62f4ce25..085b2f66f 100644 --- a/lib/nnc/ccv_nnc_symbolic_graph_memory_reduction.c +++ b/lib/nnc/ccv_nnc_symbolic_graph_memory_reduction.c @@ -38,7 +38,7 @@ static ccv_sparse_matrix_t* _ccv_nnc_exec_dep_new(const ccv_nnc_symbolic_graph_t continue; for (i = 0; i < node->outgoings->rnum; i++) { - int outgoing = *(int*)ccv_array_get(node->outgoings, i); + const int outgoing = *(int*)ccv_array_get(node->outgoings, i); const int32_t one = 1; ccv_numeric_data_t cell = ccv_get_sparse_matrix_cell(exec_dep, outgoing, idx); /* If not found, set, if the current node is the destination node, no need @@ -48,6 +48,7 @@ static ccv_sparse_matrix_t* _ccv_nnc_exec_dep_new(const ccv_nnc_symbolic_graph_t if (buf_size > 0) { ccv_sparse_matrix_vector_t* vector = ccv_get_sparse_matrix_vector(exec_dep, outgoing); + assert(vector); for (j = 0; j < buf_size; j++) /* set with all idx's dependencies as well */ { ccv_numeric_data_t cell = ccv_get_sparse_matrix_cell_from_vector(exec_dep, vector, buf[j * 2]); diff --git a/lib/nnc/makefile b/lib/nnc/makefile index 9ab28d50d..87ffd35e1 100644 --- a/lib/nnc/makefile +++ b/lib/nnc/makefile @@ -3,7 +3,7 @@ include ../config.mk CFLAGS := -O3 -Wall -I"../" $(CFLAGS) NVFLAGS := -O3 $(NVFLAGS) -SRCS := ccv_nnc_cmd.c ccv_nnc_tensor.c ccv_nnc_tensor_io.c ccv_nnc_stream.c ccv_nnc_micro.c ccv_nnc_micro_core.c ccv_nnc_micro_interpret.c ccv_nnc_micro_simplify.c ccv_nnc_graph.c ccv_nnc_symbolic_graph.c ccv_nnc_symbolic_graph_io.c ccv_nnc_symbolic_graph_compile.c ccv_nnc_symbolic_graph_backward.c ccv_nnc_symbolic_graph_while.c ccv_nnc_graph_while.c ccv_nnc_tensor_tape.c ccv_nnc_symbolic_graph_case_of.c ccv_nnc_graph_case_of.c ccv_nnc_symbolic_graph_minimize.c ccv_nnc_symbolic_graph_parallel.c ccv_nnc_symbolic_graph_simplify.c ccv_nnc_symbolic_graph_memory_compression.c ccv_nnc_graph_run.c ccv_nnc_xpu_alloc.c ccv_nnc_dynamic_graph.c ccv_nnc_dynamic_graph_alloc.c ccv_nnc_dynamic_graph_backward.c ccv_nnc_dynamic_graph_apply_gradients.c ccv_nnc_dynamic_graph_minimize.c ccv_nnc_dynamic_graph_evaluate.c ccv_cnnp_dataframe.c ccv_cnnp_dataframe_core.c ccv_cnnp_dataframe_addons.c ccv_cnnp_dataframe_csv.c ccv_cnnp_model.c ccv_cnnp_model_io.c ccv_cnnp_model_core.c ccv_cnnp_model_addons.c co.c +SRCS := ccv_nnc_cmd.c ccv_nnc_tensor.c ccv_nnc_tensor_io.c ccv_nnc_stream.c ccv_nnc_micro.c ccv_nnc_micro_core.c ccv_nnc_micro_interpret.c ccv_nnc_micro_simplify.c ccv_nnc_graph.c ccv_nnc_symbolic_graph.c ccv_nnc_symbolic_graph_io.c ccv_nnc_symbolic_graph_compile.c ccv_nnc_symbolic_graph_backward.c ccv_nnc_symbolic_graph_while.c ccv_nnc_graph_while.c ccv_nnc_tensor_tape.c ccv_nnc_symbolic_graph_case_of.c ccv_nnc_graph_case_of.c ccv_nnc_symbolic_graph_minimize.c ccv_nnc_symbolic_graph_parallel.c ccv_nnc_symbolic_graph_simplify.c ccv_nnc_symbolic_graph_memory_compression.c ccv_nnc_symbolic_graph_memory_reduction.c ccv_nnc_graph_run.c ccv_nnc_xpu_alloc.c ccv_nnc_dynamic_graph.c ccv_nnc_dynamic_graph_alloc.c ccv_nnc_dynamic_graph_backward.c ccv_nnc_dynamic_graph_apply_gradients.c ccv_nnc_dynamic_graph_minimize.c ccv_nnc_dynamic_graph_evaluate.c ccv_cnnp_dataframe.c ccv_cnnp_dataframe_core.c ccv_cnnp_dataframe_addons.c ccv_cnnp_dataframe_csv.c ccv_cnnp_model.c ccv_cnnp_model_io.c ccv_cnnp_model_core.c ccv_cnnp_model_addons.c co.c SRC_OBJS := $(patsubst %.c,%.o,$(SRCS))