-
Notifications
You must be signed in to change notification settings - Fork 91
Add support for C++ benchmarks. #99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
4ef9e38
2dc3894
3dd45ef
72b88ad
1cdcc74
17c69fe
53f81f7
67560c8
a9b5218
3c3700c
61bbffa
89d29e7
5db9fc2
c6a1a81
dc3df69
eb5d0b6
2f035fc
1c5d85c
9a96d72
b5fbb12
a8239a1
8e1f93a
b7ab8e4
068adfd
ef25201
3fa330f
1ff7b98
faf4ffd
bd9a88a
85ff323
6ae77be
6114498
330d543
53c3c07
3f55a9d
5a1557d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| { | ||
| "timeout": 120, | ||
| "memory": 128, | ||
| "languages": ["python", "nodejs"], | ||
| "languages": ["python", "nodejs", "cpp"], | ||
| "modules": [] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
|
|
||
| #include <aws/core/Aws.h> | ||
| #include <aws/core/utils/json/JsonSerializer.h> | ||
| #include <aws/lambda-runtime/runtime.h> | ||
|
|
||
| #include <thread> | ||
| #include <iostream> | ||
|
|
||
| Aws::Utils::Json::JsonValue function(Aws::Utils::Json::JsonView json) | ||
| { | ||
| int sleep = json.GetInteger("sleep"); | ||
|
|
||
| std::chrono::seconds timespan(sleep); | ||
| std::this_thread::sleep_for(timespan); | ||
mcopik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| //std::string res_json = "{ \"result\": " + std::to_string(sleep) + "}"; | ||
| //return aws::lambda_runtime::invocation_response::success(res_json, "application/json"); | ||
| Aws::Utils::Json::JsonValue val; | ||
| val.WithObject("result", std::to_string(sleep)); | ||
| return val; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| { | ||
| "timeout": 60, | ||
| "memory": 256, | ||
| "languages": ["python", "nodejs"], | ||
| "modules": ["storage"] | ||
| "languages": ["python", "nodejs", "cpp"], | ||
| "modules": ["storage"], | ||
| "cpp_dependencies": ["opencv", "boost"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
|
|
||
| #include <opencv2/opencv.hpp> | ||
| #include <opencv2/imgcodecs.hpp> | ||
|
|
||
| void thumbnailer(cv::Mat &in, int64_t width, int64_t height, cv::Mat &out) | ||
| { | ||
| try | ||
| { | ||
| // Calculate thumbnail size while maintaining aspect ratio | ||
| int orig_width = in.cols; | ||
| int orig_height = in.rows; | ||
|
|
||
| double scale_w = static_cast<double>(width) / orig_width; | ||
| double scale_h = static_cast<double>(height) / orig_height; | ||
| double scale = std::min(scale_w, scale_h); // Use smaller scale to fit within bounds | ||
|
|
||
| int new_width = static_cast<int>(orig_width * scale); | ||
| int new_height = static_cast<int>(orig_height * scale); | ||
|
|
||
| // Resize image (equivalent to PIL's thumbnail method) | ||
| cv::resize(in, out, cv::Size(new_width, new_height), cv::INTER_LINEAR); | ||
| } | ||
| catch (const cv::Exception &e) | ||
| { | ||
| std::cerr << "OpenCV error: " << e.what() << std::endl; | ||
| } | ||
| } | ||
|
Comment on lines
+7
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rethrow exceptions to avoid swallowing errors. The catch block logs the error but doesn't rethrow, leaving the Apply this diff to rethrow the exception: catch (const cv::Exception &e)
{
std::cerr << "OpenCV error: " << e.what() << std::endl;
+ throw;
}🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,117 @@ | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| #include <aws/core/Aws.h> | ||||||||||||||||||||||||||||||||||||||||
| #include <aws/core/utils/json/JsonSerializer.h> | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| #include <boost/uuid/uuid_generators.hpp> | ||||||||||||||||||||||||||||||||||||||||
| #include <boost/uuid/uuid.hpp> | ||||||||||||||||||||||||||||||||||||||||
| #include <boost/uuid/uuid_io.hpp> | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| #include <iostream> | ||||||||||||||||||||||||||||||||||||||||
| #include <vector> | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| #include "function.hpp" | ||||||||||||||||||||||||||||||||||||||||
| #include "storage.hpp" | ||||||||||||||||||||||||||||||||||||||||
| #include "utils.hpp" | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Aws::Utils::Json::JsonValue function(Aws::Utils::Json::JsonView request) | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| sebs::Storage client_ = sebs::Storage::get_client(); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| auto bucket_obj = request.GetObject("bucket"); | ||||||||||||||||||||||||||||||||||||||||
| if (!bucket_obj.IsObject()) | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| Aws::Utils::Json::JsonValue error; | ||||||||||||||||||||||||||||||||||||||||
| error.WithString("error", "Bucket object is not valid."); | ||||||||||||||||||||||||||||||||||||||||
| return error; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| auto bucket_name = bucket_obj.GetString("bucket"); | ||||||||||||||||||||||||||||||||||||||||
| auto input_key_prefix = bucket_obj.GetString("input"); | ||||||||||||||||||||||||||||||||||||||||
| auto output_key_prefix = bucket_obj.GetString("output"); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| auto image_name = request.GetObject("object").GetString("key"); | ||||||||||||||||||||||||||||||||||||||||
| auto width = request.GetObject("object").GetInteger("width"); | ||||||||||||||||||||||||||||||||||||||||
| auto height = request.GetObject("object").GetInteger("height"); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+31
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate presence and types of object.key/width/height. Avoid crashes when fields are missing or wrong types. Apply this diff: - auto image_name = request.GetObject("object").GetString("key");
- auto width = request.GetObject("object").GetInteger("width");
- auto height = request.GetObject("object").GetInteger("height");
+ if (!request.ValueExists("object") ||
+ !request.GetObject("object").ValueExists("key") ||
+ !request.GetObject("object").ValueExists("width") ||
+ !request.GetObject("object").ValueExists("height")) {
+ Aws::Utils::Json::JsonValue error;
+ error.WithString("error", "Missing object.key/width/height.");
+ return error;
+ }
+ auto image_name = request.GetObject("object").GetString("key");
+ auto width = request.GetObject("object").GetInteger("width");
+ auto height = request.GetObject("object").GetInteger("height");
+ if (width <= 0 || height <= 0) {
+ Aws::Utils::Json::JsonValue error;
+ error.WithString("error", "Width/height must be positive.");
+ return error;
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| std::string body_str; | ||||||||||||||||||||||||||||||||||||||||
| uint64_t download_time; | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| std::string input_key = input_key_prefix + "/" + image_name; | ||||||||||||||||||||||||||||||||||||||||
| auto ans = client_.download_file(bucket_name, input_key); | ||||||||||||||||||||||||||||||||||||||||
| body_str = std::get<0>(ans); | ||||||||||||||||||||||||||||||||||||||||
| download_time = std::get<1>(ans); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| if (body_str.empty()) | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| Aws::Utils::Json::JsonValue error; | ||||||||||||||||||||||||||||||||||||||||
| error.WithString("error", "Failed to download object from S3: " + input_key); | ||||||||||||||||||||||||||||||||||||||||
| return error; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| std::vector<char> vectordata(body_str.begin(), body_str.end()); | ||||||||||||||||||||||||||||||||||||||||
| cv::Mat image = imdecode(cv::Mat(vectordata), 1); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Apply the thumbnailer function and measure the computing time | ||||||||||||||||||||||||||||||||||||||||
| cv::Mat image2; | ||||||||||||||||||||||||||||||||||||||||
| uint64_t computing_time; | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| auto start_time = timeSinceEpochMicrosec(); | ||||||||||||||||||||||||||||||||||||||||
| thumbnailer(image, width, height, image2); | ||||||||||||||||||||||||||||||||||||||||
| computing_time = timeSinceEpochMicrosec() - start_time; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| std::vector<unsigned char> out_buffer; | ||||||||||||||||||||||||||||||||||||||||
| cv::imencode(".jpg", image2, out_buffer); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Create a unique key name for the output image | ||||||||||||||||||||||||||||||||||||||||
| std::string key_name; | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| std::string output_key = output_key_prefix + "/" + image_name; | ||||||||||||||||||||||||||||||||||||||||
| std::string name, extension; | ||||||||||||||||||||||||||||||||||||||||
| if (output_key.find_last_of('.') != std::string::npos) | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| name = output_key.substr(0, output_key.find_last_of('.')); | ||||||||||||||||||||||||||||||||||||||||
| extension = output_key.substr(output_key.find_last_of('.')); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| name = output_key; | ||||||||||||||||||||||||||||||||||||||||
| extension = ""; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| key_name = name + "." | ||||||||||||||||||||||||||||||||||||||||
| + boost::uuids::to_string(boost::uuids::random_generator()()) | ||||||||||||||||||||||||||||||||||||||||
| + extension; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Upload the resulting image to S3 | ||||||||||||||||||||||||||||||||||||||||
| // If the upload fails, return an error | ||||||||||||||||||||||||||||||||||||||||
| Aws::String upload_data(out_buffer.begin(), out_buffer.end()); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| uint64_t upload_time = client_.upload_random_file( | ||||||||||||||||||||||||||||||||||||||||
| bucket_name, key_name, true, | ||||||||||||||||||||||||||||||||||||||||
| reinterpret_cast<char *>(out_buffer.data()), out_buffer.size()); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| if (upload_time == 0) | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| Aws::Utils::Json::JsonValue error; | ||||||||||||||||||||||||||||||||||||||||
| error.WithString("error", "Failed to upload object to S3: " + key_name); | ||||||||||||||||||||||||||||||||||||||||
| return error; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Aws::Utils::Json::JsonValue val; | ||||||||||||||||||||||||||||||||||||||||
| Aws::Utils::Json::JsonValue result; | ||||||||||||||||||||||||||||||||||||||||
| Aws::Utils::Json::JsonValue measurements; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| result.WithString("bucket", bucket_name); | ||||||||||||||||||||||||||||||||||||||||
| result.WithString("key", key_name); | ||||||||||||||||||||||||||||||||||||||||
| val.WithObject("result", result); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| measurements.WithInteger("download_time", download_time); | ||||||||||||||||||||||||||||||||||||||||
| measurements.WithInteger("upload_time", upload_time); | ||||||||||||||||||||||||||||||||||||||||
| measurements.WithInteger("compute_time", computing_time); | ||||||||||||||||||||||||||||||||||||||||
| measurements.WithInteger("download_size", vectordata.size()); | ||||||||||||||||||||||||||||||||||||||||
| measurements.WithInteger("upload_size", out_buffer.size()); | ||||||||||||||||||||||||||||||||||||||||
| val.WithObject("measurements", measurements); | ||||||||||||||||||||||||||||||||||||||||
| return val; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| { | ||
| "timeout": 60, | ||
| "memory": 512, | ||
| "languages": ["python"], | ||
| "modules": ["storage"] | ||
| "languages": ["python", "cpp"], | ||
| "modules": ["storage"], | ||
| "cpp_dependencies": ["torch", "opencv"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| #include <aws/core/Aws.h> | ||
| #include <aws/core/utils/json/JsonSerializer.h> | ||
|
|
||
| #include <boost/uuid/uuid_generators.hpp> | ||
| #include <boost/uuid/uuid.hpp> | ||
| #include <boost/uuid/uuid_io.hpp> | ||
|
|
||
| #include <iostream> | ||
| #include <vector> | ||
|
|
||
| #include "utils.hpp" | ||
| #include "storage.hpp" | ||
|
|
||
| #include <torch/torch.h> | ||
| #include <torch/script.h> | ||
|
|
||
| #include <torchvision/vision.h> | ||
| #include <torchvision/models/resnet.h> | ||
| #include <opencv2/imgproc/imgproc.hpp> | ||
| #include <opencv2/opencv.hpp> | ||
|
|
||
|
|
||
| #define kIMAGE_SIZE 224 | ||
| #define kCHANNELS 3 | ||
| #define kTOP_K 3 | ||
|
|
||
|
|
||
| bool load_image(cv::Mat &image) | ||
| { | ||
|
|
||
| if (image.empty() || !image.data) | ||
| { | ||
| return false; | ||
| } | ||
| cv::cvtColor(image, image, cv::COLOR_BGR2RGB); | ||
|
|
||
| int w = image.size().width, h = image.size().height; | ||
| cv::Size scale((int)256 * ((float)w) / h, 256); | ||
| cv::resize(image, image, scale); | ||
| w = image.size().width, h = image.size().height; | ||
| image = image(cv::Range(16, 240), cv::Range(80, 304)); | ||
| image.convertTo(image, CV_32FC3, 1.0f / 255.0f); | ||
|
|
||
|
Comment on lines
+37
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unsafe fixed ROI crop; center-crop robustly after resizing the shorter side. Current indices can go out of bounds (e.g., width 256). Replace with size-aware crop. - int w = image.size().width, h = image.size().height;
- cv::Size scale((int)256 * ((float)w) / h, 256);
- cv::resize(image, image, scale);
- w = image.size().width, h = image.size().height;
- image = image(cv::Range(16, 240), cv::Range(80, 304));
- image.convertTo(image, CV_32FC3, 1.0f / 255.0f);
+ int w = image.cols, h = image.rows;
+ int short_side = std::min(w, h);
+ cv::Size scaled(
+ static_cast<int>(std::round(w * 256.0 / short_side)),
+ static_cast<int>(std::round(h * 256.0 / short_side)));
+ cv::resize(image, image, scaled);
+ w = image.cols; h = image.rows;
+ int x = std::max(0, std::min((w - kIMAGE_SIZE) / 2, w - kIMAGE_SIZE));
+ int y = std::max(0, std::min((h - kIMAGE_SIZE) / 2, h - kIMAGE_SIZE));
+ image = image(cv::Rect(x, y, kIMAGE_SIZE, kIMAGE_SIZE));
+ image.convertTo(image, CV_32FC3, 1.0f / 255.0f);
|
||
| return true; | ||
| } | ||
|
|
||
| int recognition(cv::Mat &image) | ||
| { | ||
|
|
||
| static bool initialized = false; | ||
| static torch::jit::script::Module module; | ||
| if (!initialized) | ||
| { | ||
| try | ||
| { | ||
| std::cout << "Initialize ResNet50 model" << std::endl; | ||
| module = torch::jit::load("./resnet50.pt"); | ||
| } | ||
| catch (const c10::Error &e) | ||
| { | ||
| std::cerr << "error loading the model\n"; | ||
| return -1; | ||
| } | ||
| initialized = true; | ||
| } | ||
|
|
||
| if (load_image(image)) | ||
| { | ||
|
|
||
| auto input_tensor = torch::from_blob( | ||
| image.data, {1, kIMAGE_SIZE, kIMAGE_SIZE, kCHANNELS}); | ||
| input_tensor = input_tensor.permute({0, 3, 1, 2}); | ||
|
|
||
| input_tensor[0][0] = input_tensor[0][0].sub_(0.485).div_(0.229); | ||
| input_tensor[0][1] = input_tensor[0][1].sub_(0.456).div_(0.224); | ||
| input_tensor[0][2] = input_tensor[0][2].sub_(0.406).div_(0.225); | ||
|
|
||
| torch::Tensor out_tensor = module.forward({input_tensor}).toTensor(); | ||
| auto results = out_tensor.sort(-1, true); | ||
| auto softmaxs = std::get<0>(results)[0].softmax(0); | ||
| auto indexs = std::get<1>(results)[0]; | ||
|
|
||
| std::cout << indexs[0].item<int>() << " " << softmaxs[0].item<double>() << std::endl; | ||
| return indexs[0].item<int>(); | ||
|
|
||
|
|
||
| } | ||
|
|
||
| return -1; | ||
| } | ||
|
|
||
| Aws::Utils::Json::JsonValue function(Aws::Utils::Json::JsonView request) | ||
| { | ||
| sebs::Storage client_ = sebs::Storage::get_client(); | ||
|
|
||
| auto bucket_obj = request.GetObject("bucket"); | ||
| if (!bucket_obj.IsObject()) | ||
| { | ||
| Aws::Utils::Json::JsonValue error; | ||
| error.WithString("error", "Bucket object is not valid."); | ||
| return error; | ||
| } | ||
|
|
||
| auto bucket_name = bucket_obj.GetString("bucket"); | ||
| auto input_prefix = bucket_obj.GetString("input"); | ||
| auto model_prefix = bucket_obj.GetString("model"); | ||
| auto key = request.GetObject("object").GetString("input"); | ||
| auto model_key = request.GetObject("object").GetString("model"); | ||
|
|
||
|
Comment on lines
+96
to
+109
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate request schema before GetString() calls. Guard against missing keys to prevent exceptions. - auto bucket_obj = request.GetObject("bucket");
- if (!bucket_obj.IsObject())
+ if (!request.ValueExists("bucket") || !request.GetObject("bucket").IsObject())
{
Aws::Utils::Json::JsonValue error;
error.WithString("error", "Bucket object is not valid.");
return error;
}
-
- auto bucket_name = bucket_obj.GetString("bucket");
- auto input_prefix = bucket_obj.GetString("input");
- auto model_prefix = bucket_obj.GetString("model");
- auto key = request.GetObject("object").GetString("input");
- auto model_key = request.GetObject("object").GetString("model");
+ auto bucket_obj = request.GetObject("bucket");
+ if (!bucket_obj.ValueExists("bucket") || !bucket_obj.ValueExists("input") || !bucket_obj.ValueExists("model")
+ || !request.ValueExists("object")
+ || !request.GetObject("object").ValueExists("input")
+ || !request.GetObject("object").ValueExists("model")) {
+ Aws::Utils::Json::JsonValue error;
+ error.WithString("error", "Missing required keys: bucket.bucket/input/model and object.input/model.");
+ return error;
+ }
+ auto bucket_name = bucket_obj.GetString("bucket");
+ auto input_prefix = bucket_obj.GetString("input");
+ auto model_prefix = bucket_obj.GetString("model");
+ auto key = request.GetObject("object").GetString("input");
+ auto model_key = request.GetObject("object").GetString("model");🤖 Prompt for AI Agents |
||
|
|
||
| Aws::Utils::Json::JsonValue val; | ||
| Aws::Utils::Json::JsonValue result; | ||
| Aws::Utils::Json::JsonValue measurements; | ||
|
|
||
| return val; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| { | ||
| "timeout": 120, | ||
| "memory": 512, | ||
| "languages": ["python"], | ||
| "modules": [] | ||
| "languages": ["python", "cpp"], | ||
| "modules": [], | ||
| "cpp_dependencies": ["igraph"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
|
|
||
| #include <igraph.h> | ||
|
|
||
| #include <cfloat> | ||
|
|
||
| #include "utils.hpp" | ||
|
|
||
| igraph_real_t graph_pagerank | ||
| (int size, uint64_t seed, uint64_t &graph_generation_time_ms, uint64_t &compute_pr_time_ms) | ||
| { | ||
| igraph_t graph; | ||
| igraph_vector_t pagerank; | ||
| igraph_real_t value; | ||
|
|
||
| igraph_rng_seed(igraph_rng_default(), seed); | ||
| { | ||
| uint64_t start_time = timeSinceEpochMicrosec(); | ||
| igraph_barabasi_game( | ||
| /* graph= */ &graph, | ||
| /* n= */ size, | ||
| /* power= */ 1, | ||
| /* m= */ 10, | ||
| /* outseq= */ NULL, | ||
|
Comment on lines
+17
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Boundary checks for Barabási–Albert parameters. m=10 requires size > 10; for smaller graphs igraph may error. Guard inputs or scale m. Apply this diff: - igraph_rng_seed(igraph_rng_default(), seed);
+ igraph_rng_seed(igraph_rng_default(), seed);
{
uint64_t start_time = timeSinceEpochMicrosec();
- igraph_barabasi_game(
+ int m = size > 1 ? std::min(10, size - 1) : 1;
+ igraph_barabasi_game(
/* graph= */ &graph,
/* n= */ size,
/* power= */ 1,
- /* m= */ 10,
+ /* m= */ m,Also applies to: 29-35 🤖 Prompt for AI Agents |
||
| /* outpref= */ 0, | ||
| /* A= */ 1.0, | ||
| /* directed= */ 0, | ||
| /* algo= */ IGRAPH_BARABASI_PSUMTREE_MULTIPLE, | ||
|
Comment on lines
+26
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Directedness mismatch: graph is undirected, PageRank called as directed. You create an undirected graph (directed=0) but call igraph_pagerank with IGRAPH_DIRECTED. Use IGRAPH_UNDIRECTED or generate a directed graph consistently. Apply this diff to keep it undirected: - /* directed= */ 0,
+ /* directed= */ 0,
@@
- igraph_vss_all(), IGRAPH_DIRECTED,
+ igraph_vss_all(), IGRAPH_UNDIRECTED,Also applies to: 36-40 🤖 Prompt for AI Agents |
||
| /* start_from= */ 0 | ||
| ); | ||
| graph_generation_time_ms = (timeSinceEpochMicrosec() - start_time); | ||
| } | ||
|
|
||
| igraph_vector_init(&pagerank, 0); | ||
| { | ||
| uint64_t start_time = timeSinceEpochMicrosec(); | ||
| igraph_pagerank(&graph, IGRAPH_PAGERANK_ALGO_PRPACK, | ||
| &pagerank, &value, | ||
| igraph_vss_all(), IGRAPH_DIRECTED, | ||
| /* damping */ 0.85, /* weights */ NULL, | ||
| NULL /* not needed with PRPACK method */); | ||
| compute_pr_time_ms = (timeSinceEpochMicrosec() - start_time); | ||
| } | ||
| /* Check that the eigenvalue is 1, as expected. */ | ||
| if (fabs(value - 1.0) > 32*DBL_EPSILON) { | ||
| fprintf(stderr, "PageRank failed to converge.\n"); | ||
| return 1; | ||
| } | ||
|
Comment on lines
+44
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Early return leaks resources (graph and pagerank vector). On convergence failure you return without destroying pagerank and graph. Apply this minimal fix: if (fabs(value - 1.0) > 32*DBL_EPSILON) {
fprintf(stderr, "PageRank failed to converge.\n");
- return 1;
+ igraph_vector_destroy(&pagerank);
+ igraph_destroy(&graph);
+ return 1;
}Also applies to: 51-54 🤖 Prompt for AI Agents |
||
|
|
||
| igraph_real_t result = VECTOR(pagerank)[0]; | ||
|
|
||
| igraph_vector_destroy(&pagerank); | ||
| igraph_destroy(&graph); | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.