未验证 提交 c0919292 编写于 作者: G groot 提交者: GitHub

improve sdk_qps (#1804)

* improve sdk_qps
Signed-off-by: Nyhmo <yihua.mo@zilliz.com>

* refine sdk code
Signed-off-by: Nyhmo <yihua.mo@zilliz.com>

* sdk_qps improve
Signed-off-by: Ngroot <yihua.mo@zilliz.com>

* sdk_qps improve
Signed-off-by: Ngroot <yihua.mo@zilliz.com>

* add log
Signed-off-by: Ngroot <yihua.mo@zilliz.com>
上级 b995ccfb
......@@ -27,14 +27,28 @@ main(int argc, char* argv[]) {
static struct option long_options[] = {{"server", optional_argument, nullptr, 's'},
{"port", optional_argument, nullptr, 'p'},
{"help", no_argument, nullptr, 'h'},
{"collection_name", no_argument, nullptr, 't'},
{"index", optional_argument, nullptr, 'i'},
{"index_file_size", optional_argument, nullptr, 'f'},
{"nlist", optional_argument, nullptr, 'l'},
{"metric", optional_argument, nullptr, 'm'},
{"dimension", optional_argument, nullptr, 'd'},
{"rowcount", optional_argument, nullptr, 'r'},
{"concurrency", optional_argument, nullptr, 'c'},
{"query_count", optional_argument, nullptr, 'q'},
{"nq", optional_argument, nullptr, 'n'},
{"topk", optional_argument, nullptr, 'k'},
{"nprobe", optional_argument, nullptr, 'b'},
{"print", optional_argument, nullptr, 'v'},
{nullptr, 0, nullptr, 0}};
int option_index = 0;
std::string address = "127.0.0.1", port = "19530";
app_name = argv[0];
TestParameters parameters;
int value;
while ((value = getopt_long(argc, argv, "s:p:h", long_options, &option_index)) != -1) {
while ((value = getopt_long(argc, argv, "s:p:t:i:f:l:m:d:r:c:q:n:k:b:vh", long_options, &option_index)) != -1) {
switch (value) {
case 's': {
char* address_ptr = strdup(optarg);
......@@ -48,6 +62,82 @@ main(int argc, char* argv[]) {
free(port_ptr);
break;
}
case 't': {
char* ptr = strdup(optarg);
parameters.collection_name_ = ptr;
free(ptr);
break;
}
case 'i': {
char* ptr = strdup(optarg);
parameters.index_type_ = atol(ptr);
free(ptr);
break;
}
case 'f': {
char* ptr = strdup(optarg);
parameters.index_file_size_ = atol(ptr);
free(ptr);
break;
}
case 'l': {
char* ptr = strdup(optarg);
parameters.nlist_ = atol(ptr);
free(ptr);
break;
}
case 'm': {
char* ptr = strdup(optarg);
parameters.metric_type_ = atol(ptr);
free(ptr);
break;
}
case 'd': {
char* ptr = strdup(optarg);
parameters.dimensions_ = atol(ptr);
free(ptr);
break;
}
case 'r': {
char* ptr = strdup(optarg);
parameters.row_count_ = atol(ptr);
free(ptr);
break;
}
case 'c': {
char* ptr = strdup(optarg);
parameters.concurrency_ = atol(ptr);
free(ptr);
break;
}
case 'q': {
char* ptr = strdup(optarg);
parameters.query_count_ = atol(ptr);
free(ptr);
break;
}
case 'n': {
char* ptr = strdup(optarg);
parameters.nq_ = atol(ptr);
free(ptr);
break;
}
case 'k': {
char* ptr = strdup(optarg);
parameters.topk_ = atol(ptr);
free(ptr);
break;
}
case 'b': {
char* ptr = strdup(optarg);
parameters.nprobe_ = atol(ptr);
free(ptr);
break;
}
case 'v': {
parameters.print_result_ = true;
break;
}
case 'h':
default:
print_help(app_name);
......@@ -56,9 +146,9 @@ main(int argc, char* argv[]) {
}
ClientTest test(address, port);
test.Test();
test.Test(parameters);
printf("Client stop...\n");
printf("Client exits ...\n");
return 0;
}
......@@ -66,8 +156,25 @@ void
print_help(const std::string& app_name) {
printf("\n Usage: %s [OPTIONS]\n\n", app_name.c_str());
printf(" Options:\n");
printf(" -s --server Server address, default 127.0.0.1\n");
printf(" -p --port Server port, default 19530\n");
printf(" -s --server Server address, default:127.0.0.1\n");
printf(" -p --port Server port, default:19530\n");
printf(" -t --collection_name target collection name, specify this will ignore collection parameters, "
"default empty\n");
printf(" -h --help Print help information\n");
printf(" -i --index "
"Collection index type(1=IDMAP, 2=IVFLAT, 3=IVFSQ8, 5=IVFSQ8H), default:3\n");
printf(" -f --index_file_size Collection index file size, default:1024\n");
printf(" -l --nlist Collection index nlist, default:16384\n");
printf(" -m --metric "
"Collection metric type(1=L2, 2=IP, 3=HAMMING, 4=JACCARD, 5=TANIMOTO, 6=SUBSTRUCTURE, 7=SUPERSTRUCTURE), "
"default:1\n");
printf(" -d --dimension Collection dimension, default:128\n");
printf(" -r --rowcount Collection total row count(unit:million), default:1\n");
printf(" -c --concurrency Max client connections, default:20\n");
printf(" -q --query_count Query total count, default:1000\n");
printf(" -n --nq nq of each query, default:1\n");
printf(" -k --topk topk of each query, default:10\n");
printf(" -b --nprobe nprobe of each query, default:16\n");
printf(" -v --print_result Print query result, default:false\n");
printf("\n");
}
......@@ -11,6 +11,7 @@
#include "examples/utils/TimeRecorder.h"
#include "examples/utils/Utils.h"
#include "examples/utils/ThreadPool.h"
#include "examples/qps/src/ClientTest.h"
#include <iostream>
......@@ -19,74 +20,45 @@
#include <vector>
namespace {
const char* COLLECTION_NAME = milvus_sdk::Utils::GenCollectionName().c_str();
constexpr int64_t COLLECTION_DIMENSION = 128;
constexpr int64_t COLLECTION_INDEX_FILE_SIZE = 512;
constexpr milvus::MetricType COLLECTION_METRIC_TYPE = milvus::MetricType::L2;
constexpr int64_t BATCH_ENTITY_COUNT = 100000;
constexpr int64_t NQ = 5;
constexpr int64_t TOP_K = 10;
constexpr int64_t NPROBE = 16;
constexpr int64_t ADD_ENTITY_LOOP = 10;
constexpr milvus::IndexType INDEX_TYPE = milvus::IndexType::IVFSQ8;
constexpr int32_t NLIST = 16384;
// parallel query setting
constexpr int32_t QUERY_THREAD_COUNT = 20;
constexpr int32_t TOTAL_QUERY_COUNT = 1000;
bool PRINT_RESULT = false;
bool
InsertEntities(std::shared_ptr<milvus::Connection>& conn) {
for (int i = 0; i < ADD_ENTITY_LOOP; i++) {
std::vector<milvus::Entity> entity_array;
std::vector<int64_t> record_ids;
int64_t begin_index = i * BATCH_ENTITY_COUNT;
{ // generate vectors
milvus_sdk::TimeRecorder rc("Build entities No." + std::to_string(i));
milvus_sdk::Utils::BuildEntities(begin_index,
begin_index + BATCH_ENTITY_COUNT,
entity_array,
record_ids,
COLLECTION_DIMENSION);
}
std::string title = "Insert " + std::to_string(entity_array.size()) + " entities No." + std::to_string(i);
milvus_sdk::TimeRecorder rc(title);
milvus::Status stat = conn->Insert(COLLECTION_NAME, "", entity_array, record_ids);
std::cout << "InsertEntities function call status: " << stat.message() << std::endl;
std::cout << "Returned id array count: " << record_ids.size() << std::endl;
stat = conn->FlushCollection(COLLECTION_NAME);
IsSupportedIndex(int64_t index) {
if (index != (int64_t)milvus::IndexType::FLAT
&& index != (int64_t)milvus::IndexType::IVFFLAT
&& index != (int64_t)milvus::IndexType::IVFSQ8
&& index != (int64_t)milvus::IndexType::IVFSQ8H) {
std::cout << "Unsupported index type: " << index << std::endl;
return false;
}
return true;
}
void
PrintSearchResult(int64_t batch_num, const milvus::TopKQueryResult& result) {
if (!PRINT_RESULT) {
return;
class ConnectionWrapper {
public:
explicit ConnectionWrapper(std::shared_ptr<milvus::Connection>& connection)
: connection_(connection) {
}
std::cout << "No." << batch_num << " query result:" << std::endl;
for (size_t i = 0; i < result.size(); i++) {
std::cout << "\tNQ_" << i;
const milvus::QueryResult& one_result = result[i];
size_t topk = one_result.ids.size();
for (size_t j = 0; j < topk; j++) {
std::cout << "\t[" << one_result.ids[j] << ", " << one_result.distances[j] << "]";
~ConnectionWrapper() {
if (connection_) {
milvus::Connection::Destroy(connection_);
}
std::cout << std::endl;
}
}
std::shared_ptr<milvus::Connection>& Connection() {
return connection_;
}
private:
std::shared_ptr<milvus::Connection> connection_;
};
} // namespace
ClientTest::ClientTest(const std::string& address, const std::string& port)
: server_ip_(address), server_port_(port), query_thread_pool_(QUERY_THREAD_COUNT, QUERY_THREAD_COUNT * 2) {
: server_ip_(address), server_port_(port) {
}
ClientTest::~ClientTest() {
......@@ -105,103 +77,284 @@ ClientTest::Connect() {
return conn;
}
bool
ClientTest::CheckParameters(const TestParameters& parameters) {
if (!IsSupportedIndex(parameters.index_type_)) {
return false;
}
if (parameters.metric_type_ <= 0 || parameters.metric_type_ > (int64_t)milvus::MetricType::SUPERSTRUCTURE) {
std::cout << "Invalid metric type: " << parameters.metric_type_ << std::endl;
return false;
}
if (parameters.row_count_ <= 0) {
std::cout << "Invalid row count: " << parameters.row_count_ << std::endl;
return false;
}
if (parameters.concurrency_ <= 0) {
std::cout << "Invalid concurrency: " << parameters.concurrency_ << std::endl;
return false;
}
if (parameters.query_count_ <= 0) {
std::cout << "Invalid query count: " << parameters.query_count_ << std::endl;
return false;
}
if (parameters.nq_ <= 0) {
std::cout << "Invalid query nq: " << parameters.nq_ << std::endl;
return false;
}
if (parameters.topk_ <= 0 || parameters.topk_ > 2048) {
std::cout << "Invalid query topk: " << parameters.topk_ << std::endl;
return false;
}
if (parameters.nprobe_ <= 0) {
std::cout << "Invalid query nprobe: " << parameters.nprobe_ << std::endl;
return false;
}
return true;
}
bool
ClientTest::BuildCollection() {
std::shared_ptr<milvus::Connection> conn = Connect();
ConnectionWrapper wrapper(conn);
if (conn == nullptr) {
return false;
}
milvus::CollectionParam
collection_param = {COLLECTION_NAME, COLLECTION_DIMENSION, COLLECTION_INDEX_FILE_SIZE, COLLECTION_METRIC_TYPE};
std::string collection_name = parameters_.collection_name_;
if (collection_name.empty()) {
collection_name = milvus_sdk::Utils::GenCollectionName();
parameters_.collection_name_ = collection_name;
}
milvus::CollectionParam collection_param = {
collection_name,
parameters_.dimensions_,
parameters_.index_file_size_,
(milvus::MetricType)parameters_.metric_type_
};
std::cout << "Create collection " << collection_param.collection_name << std::endl;
auto stat = conn->CreateCollection(collection_param);
std::cout << "CreateCollection function call status: " << stat.message() << std::endl;
if (!stat.ok()) {
std::cout << "CreateCollection function call status: " << stat.message() << std::endl;
return false;
}
InsertEntities(conn);
milvus::Connection::Destroy(conn);
CreateIndex(conn);
return true;
}
void
ClientTest::CreateIndex() {
std::shared_ptr<milvus::Connection> conn = Connect();
if (conn == nullptr) {
return;
bool
ClientTest::InsertEntities(std::shared_ptr<milvus::Connection>& conn) {
int64_t batch_count = parameters_.row_count_ * ADD_ENTITY_LOOP;
for (int i = 0; i < batch_count; i++) {
std::vector<milvus::Entity> entity_array;
std::vector<int64_t> record_ids;
int64_t begin_index = i * BATCH_ENTITY_COUNT;
{ // generate vectors
// milvus_sdk::TimeRecorder rc("Build entities No." + std::to_string(i));
milvus_sdk::Utils::BuildEntities(begin_index,
begin_index + BATCH_ENTITY_COUNT,
entity_array,
record_ids,
parameters_.dimensions_);
}
std::string title = "Insert " + std::to_string(entity_array.size()) + " entities No." + std::to_string(i);
milvus_sdk::TimeRecorder rc(title);
milvus::Status stat = conn->Insert(parameters_.collection_name_, "", entity_array, record_ids);
if (!stat.ok()) {
std::cout << "CreateIndex function call status: " << stat.message() << std::endl;
}
// std::cout << "InsertEntities function call status: " << stat.message() << std::endl;
// std::cout << "Returned id array count: " << record_ids.size() << std::endl;
stat = conn->FlushCollection(parameters_.collection_name_);
}
std::cout << "Wait create index ..." << std::endl;
JSON json_params = {{"nlist", NLIST}};
milvus::IndexParam index = {COLLECTION_NAME, INDEX_TYPE, json_params.dump()};
return true;
}
void
ClientTest::CreateIndex(std::shared_ptr<milvus::Connection>& conn) {
std::string title = "Create index " + milvus_sdk::Utils::IndexTypeName((milvus::IndexType)parameters_.index_type_);
milvus_sdk::TimeRecorder rc(title);
JSON json_params = {{"nlist", parameters_.nlist_}};
milvus::IndexParam
index = {parameters_.collection_name_, (milvus::IndexType)parameters_.index_type_, json_params.dump()};
milvus_sdk::Utils::PrintIndexParam(index);
milvus::Status stat = conn->CreateIndex(index);
if (!stat.ok()) {
std::cout << "CreateIndex function call status: " << stat.message() << std::endl;
}
}
bool
ClientTest::PreloadCollection() {
std::shared_ptr<milvus::Connection> conn = Connect();
ConnectionWrapper wrapper(conn);
if (conn == nullptr) {
return false;
}
if (!conn->HasCollection(parameters_.collection_name_)) {
std::cout << "Collection not found: " << parameters_.collection_name_ << std::endl;
return false;
}
std::string title = "Preload table " + parameters_.collection_name_;
milvus_sdk::TimeRecorder rc(title);
milvus::Status stat = conn->PreloadCollection(parameters_.collection_name_);
if (!stat.ok()) {
std::string msg = "PreloadCollection function call status: " + stat.message();
std::cout << msg << std::endl;
return false;
}
return true;
}
bool
ClientTest::GetCollectionInfo() {
std::shared_ptr<milvus::Connection> conn = Connect();
ConnectionWrapper wrapper(conn);
if (conn == nullptr) {
return false;
}
milvus::CollectionParam collection_param;
milvus::Status stat = conn->DescribeCollection(parameters_.collection_name_, collection_param);
milvus::IndexParam index_param;
stat = conn->DescribeIndex(parameters_.collection_name_, index_param);
int64_t row_count = 0;
stat = conn->CountCollection(parameters_.collection_name_, row_count);
parameters_.index_type_ = (int64_t)index_param.index_type;
if (!IsSupportedIndex(parameters_.index_type_)) {
return false;
}
parameters_.row_count_ = row_count;
parameters_.dimensions_ = collection_param.dimension;
parameters_.metric_type_ = (int64_t)collection_param.metric_type;
parameters_.index_file_size_ = collection_param.index_file_size;
return true;
}
void
ClientTest::DropCollection() {
std::shared_ptr<milvus::Connection> conn = Connect();
ConnectionWrapper wrapper(conn);
if (conn == nullptr) {
return;
}
milvus::Status stat = conn->DropCollection(COLLECTION_NAME);
std::cout << "DropCollection function call status: " << stat.message() << std::endl;
milvus::Status stat = conn->DropCollection(parameters_.collection_name_);
if (!stat.ok()) {
std::string msg = "DropCollection function call status: " + stat.message();
std::cout << msg << std::endl;
}
}
void
ClientTest::BuildSearchEntities(std::vector<EntityList>& entity_array) {
entity_array.clear();
for (int64_t i = 0; i < TOTAL_QUERY_COUNT; i++) {
for (int64_t i = 0; i < parameters_.query_count_; i++) {
std::vector<milvus::Entity> entities;
std::vector<int64_t> record_ids;
int64_t batch_index = i % ADD_ENTITY_LOOP;
int64_t offset = batch_index * BATCH_ENTITY_COUNT;
milvus_sdk::Utils::BuildEntities(offset, offset + NQ, entities, record_ids, COLLECTION_DIMENSION);
milvus_sdk::Utils::BuildEntities(offset,
offset + parameters_.nq_,
entities,
record_ids,
parameters_.dimensions_);
entity_array.emplace_back(entities);
}
// std::cout << "Build search entities finish" << std::endl;
}
void
ClientTest::Search() {
if (!PreloadCollection()) {
return;
}
if (!GetCollectionInfo()) {
return;
}
std::vector<EntityList> search_entities;
BuildSearchEntities(search_entities);
query_thread_results_.clear();
std::list<std::future<milvus::TopKQueryResult>> query_thread_results;
milvus_sdk::ThreadPool query_thread_pool(parameters_.concurrency_, parameters_.concurrency_ * 2);
auto start = std::chrono::system_clock::now();
{
std::string title = "Searching " + parameters_.collection_name_;
milvus_sdk::TimeRecorder rc(title);
// multi-threads query
for (int32_t i = 0; i < TOTAL_QUERY_COUNT; i++) {
query_thread_results_.push_back(query_thread_pool_.enqueue(&ClientTest::SearchWorker,
for (int32_t i = 0; i < parameters_.query_count_; i++) {
query_thread_results.push_back(query_thread_pool.enqueue(&ClientTest::SearchWorker,
this,
search_entities[i]));
}
// wait all query return
for (auto& iter : query_thread_results_) {
for (auto& iter : query_thread_results) {
iter.wait();
}
std::chrono::system_clock::time_point end = std::chrono::system_clock::now();
int64_t span = (std::chrono::duration_cast<std::chrono::milliseconds>(end - start)).count();
double sec = (double)span / 1000.0;
std::cout << "data information: dimension = " << COLLECTION_DIMENSION << " row_count = "
<< BATCH_ENTITY_COUNT * ADD_ENTITY_LOOP << std::endl;
std::cout << "search parameters: nq = " << NQ << " topk = " << TOP_K << " nprobe = " << NPROBE << std::endl;
std::cout << "search threads = " << QUERY_THREAD_COUNT << " total_query_count = " << TOTAL_QUERY_COUNT << std::endl;
std::cout << "search " << TOTAL_QUERY_COUNT << " times totally cost: " << span << " ms" << std::endl;
std::cout << "search qps = " << TOTAL_QUERY_COUNT / sec << std::endl;
}
// print result
int64_t index = 0;
for (auto& iter : query_thread_results_) {
PrintSearchResult(index++, iter.get());
for (auto& iter : query_thread_results) {
milvus::TopKQueryResult result = iter.get();
CheckSearchResult(index, result);
PrintSearchResult(index, result);
index++;
}
// calculate qps
std::chrono::system_clock::time_point end = std::chrono::system_clock::now();
int64_t span = (std::chrono::duration_cast<std::chrono::milliseconds>(end - start)).count();
double sec = (double)span / 1000.0;
double tps_s = parameters_.query_count_ / sec;
int64_t tps = (int64_t)tps_s;
int64_t qps = tps * parameters_.nq_;
std::cout << "TPS = " << tps << " \tQPS = " << qps << std::endl;
// print search detail statistics
JSON search_stats = JSON();
search_stats["table_name"] = parameters_.collection_name_;
search_stats["index"] = milvus_sdk::Utils::IndexTypeName((milvus::IndexType)parameters_.index_type_);
search_stats["index_file_size"] = parameters_.index_file_size_;
search_stats["nlist"] = parameters_.nlist_;
search_stats["metric"] = milvus_sdk::Utils::MetricTypeName((milvus::MetricType)parameters_.metric_type_);
search_stats["dimension"] = parameters_.dimensions_;
search_stats["row_count"] = parameters_.row_count_;
search_stats["concurrency"] = parameters_.concurrency_;
search_stats["query_count"] = parameters_.query_count_;
search_stats["nq"] = parameters_.nq_;
search_stats["topk"] = parameters_.topk_;
search_stats["nprobe"] = parameters_.nprobe_;
search_stats["qps"] = qps;
search_stats["tps"] = tps;
std::cout << search_stats.dump() << std::endl;
}
milvus::TopKQueryResult
......@@ -219,12 +372,12 @@ ClientTest::SearchWorker(EntityList& entities) {
return res;
}
JSON json_params = {{"nprobe", NPROBE}};
JSON json_params = {{"nprobe", parameters_.nprobe_}};
std::vector<std::string> partition_tags;
stat = conn->Search(COLLECTION_NAME,
stat = conn->Search(parameters_.collection_name_,
partition_tags,
entities,
TOP_K,
parameters_.topk_,
json_params.dump(),
res);
if (!stat.ok()) {
......@@ -239,20 +392,52 @@ ClientTest::SearchWorker(EntityList& entities) {
}
void
ClientTest::Test() {
if (!BuildCollection()) {
ClientTest::PrintSearchResult(int64_t batch_num, const milvus::TopKQueryResult& result) {
if (!parameters_.print_result_) {
return;
}
// search without index
std::cout << "Search without index" << std::endl;
Search();
std::cout << "No." << batch_num << " query result:" << std::endl;
for (size_t i = 0; i < result.size(); i++) {
std::cout << "\tNQ_" << i;
const milvus::QueryResult& one_result = result[i];
size_t topk = one_result.ids.size();
for (size_t j = 0; j < topk; j++) {
std::cout << "\t[" << one_result.ids[j] << ", " << one_result.distances[j] << "]";
}
std::cout << std::endl;
}
}
void
ClientTest::CheckSearchResult(int64_t batch_num, const milvus::TopKQueryResult& result) {
if (result.empty()) {
std::cout << "ERROR! No." << batch_num << " query return empty result" << std::endl;
return;
}
for (auto& res : result) {
if (res.ids.empty()) {
std::cout << "ERROR! No." << batch_num << " query return empty id" << std::endl;
return;
}
}
}
CreateIndex();
void
ClientTest::Test(const TestParameters& parameters) {
if (!CheckParameters(parameters)) {
return;
}
// search with index
std::cout << "Search with index" << std::endl;
Search();
parameters_ = parameters;
if (parameters_.collection_name_.empty()) {
if (!BuildCollection()) {
return;
}
Search();
DropCollection();
} else {
Search();
}
}
......@@ -12,7 +12,6 @@
#pragma once
#include "include/MilvusApi.h"
#include "examples/utils/ThreadPool.h"
#include <string>
#include <list>
......@@ -20,23 +19,56 @@
#include <vector>
#include <future>
struct TestParameters {
// specify this will ignore index_type/index_file_size/nlist/metric_type/dimension/dow_count
std::string collection_name_;
// collection parameters, only works when collection_name_ is empty
int64_t index_type_ = (int64_t)milvus::IndexType::IVFSQ8; // sq8
int64_t index_file_size_ = 1024; // 1024 MB
int64_t nlist_ = 16384;
int64_t metric_type_ = (int64_t)milvus::MetricType::L2; // L2
int64_t dimensions_ = 128;
int64_t row_count_ = 1; // 1 million
// query parameters
int64_t concurrency_ = 20; // 20 connections
int64_t query_count_ = 1000;
int64_t nq_ = 1;
int64_t topk_ = 10;
int64_t nprobe_ = 16;
bool print_result_ = false;
};
class ClientTest {
public:
ClientTest(const std::string&, const std::string&);
~ClientTest();
void
Test();
Test(const TestParameters& parameters);
private:
std::shared_ptr<milvus::Connection>
Connect();
bool
CheckParameters(const TestParameters& parameters);
bool
BuildCollection();
bool
InsertEntities(std::shared_ptr<milvus::Connection>& conn);
void
CreateIndex();
CreateIndex(std::shared_ptr<milvus::Connection>& conn);
bool
PreloadCollection();
bool
GetCollectionInfo();
void
DropCollection();
......@@ -51,10 +83,15 @@ class ClientTest {
milvus::TopKQueryResult
SearchWorker(EntityList& entities);
void
PrintSearchResult(int64_t batch_num, const milvus::TopKQueryResult& result);
void
CheckSearchResult(int64_t batch_num, const milvus::TopKQueryResult& result);
private:
std::string server_ip_;
std::string server_port_;
milvus_sdk::ThreadPool query_thread_pool_;
std::list<std::future<milvus::TopKQueryResult>> query_thread_results_;
TestParameters parameters_;
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册