[INVESTIGATION] ImageBuffer iterators based on Space Filling Curves
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 25/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Cần làm rõ
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- cpp
- Lĩnh vực
- computer-graphics, performance
Hướng nghiên cứu
Bắt đầu bằng cách biên dịch và chạy nghiên cứu C++ độc lập, so sánh process_ref với process_morton trên các kích thước ảnh và tích chập đã nêu. Đọc cách sử dụng ImageBuf::Iterator và ImageBuf::ConstIterator được thể hiện trong ví dụ, sau đó xác định liệu việc duyệt Morton hoặc Hilbert có mang lại lợi ích đo được hay không. Issue không định nghĩa thế nào là hoàn tất; kết quả cần xác lập bằng chứng về hiệu năng và một hướng triển khai cụ thể.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Recently I've been looking into space filling curves, in particular the Morton curve (see https://en.wikipedia.org/wiki/Z-order_curve) and the Hilbert curve (see https://en.wikipedia.org/wiki/Hilbert_curve). I've read that these curves can be used to iterate through the pixels of an image in a "cache-friendly" way as they preserve spatial locality fairly well, and thus could improve the performances of some image processing algorithms.
I've started doing some investigation work, however the results I got so far do not suggest any performance improvements when using the Morton curve to iterate: I'm applying a simple convolution with a Gaussian kernel on a 4096x4096 image (on a single thread), and iterating with ImageBuffer::Iterator vs with my custom Morton curve implementation both take on average the exact same time.
If someone has some knowledge around space filling curves, performance engineering, or simply wants to continue the investigation on their side and provide more insight on this, your help is definitely welcome!
Here is the code I wrote for this initial investigation:
#include <OpenImageIO/imageio.h>
#include <OpenImageIO/imagebuf.h>
#include <OpenImageIO/imagebufalgo.h>
#include <iostream>
#include <string>
#include <cmath>
#include <chrono>
using namespace OIIO;
void process_ref(ImageBuf & dst, const ImageBuf & src, const ImageBuf & kernel)
{
ROI roi = src.roi();
ROI kroi = kernel.roi();
ImageBuf::Iterator<float> dstit(dst);
ImageBuf::ConstIterator<float> srcit(src);
for (; !dstit.done(); ++dstit) {
float sum = 0.f;
const float* k = (const float*)kernel.localpixels();
srcit.rerange(dstit.x() + kroi.xbegin, dstit.x() + kroi.xend,
dstit.y() + kroi.ybegin, dstit.y() + kroi.yend,
0 , 1 ,
ImageBuf::WrapClamp);
for (; !srcit.done(); ++srcit, k += 1) {
sum += k[0] * srcit[0];
}
dstit[0] = sum;
}
}
void process_morton(ImageBuf & dst, const ImageBuf & src, const ImageBuf & kernel, int nbits)
{
float* pixels = static_cast<float*>(dst.localpixels());
const ImageSpec & spec = dst.spec();
const uint64_t nmax = (1 << (2 * nbits));
ROI roi = src.roi();
ROI kroi = kernel.roi();
ImageBuf::ConstIterator<float> srcit(src);
for (uint64_t i = 0; i < nmax; ++i) {
uint32_t xmorton = 0;
uint32_t ymorton = 0;
for (int j = 0; j < nbits; ++j) {
xmorton |= (i & (1 << (2 * j))) >> j;
ymorton |= (i & (1 << (2 * j + 1))) >> (j + 1);
}
float sum = 0.f;
const float* k = (const float*)kernel.localpixels();
srcit.rerange(xmorton + kroi.xbegin, xmorton + kroi.xend,
ymorton + kroi.ybegin, ymorton + kroi.yend,
0 , 1 ,
ImageBuf::WrapClamp);
for (; !srcit.done(); ++srcit, k += 1) {
sum += k[0] * srcit[0];
}
pixels[ymorton * spec.width + xmorton] = sum;
}
}
int main(int argc, char *argv[])
{
// Command-line arguments
const std::string mode = argv[1];
const int nbits = std::stoi(argv[2]);
const float kernel_size = std::stof(argv[3]);
const std::string filename = argv[4];
// Specs for image buffer
// We only use dimensions that are powers of 2,
// with an exponent specified by the user
const int xres = (1 << nbits);
const int yres = (1 << nbits);
const int nchannels = 1;
ImageSpec spec(xres, yres, nchannels, TypeDesc::FLOAT);
// Destination buffer
ImageBuf dst(spec);
// Source buffer
// Use a simple checker
ImageBuf src(spec);
float dark[3] = { 0.1, 0.1, 0.1 };
float light[3] = { 0.4, 0.4, 0.4 };
ImageBufAlgo::checker(src, 64, 64, 1, cspan<float>(dark), cspan<float>(light));
// Kernel buffer
// Use a normalized Gaussian kernel
ImageBuf kernel = ImageBufAlgo::make_kernel("gaussian", kernel_size, kernel_size);
// Apply convolution to compute the final image
// Measure elapsed time to compare iterator-based approach
// and Morton-curve-based approach
auto t_start = std::chrono::high_resolution_clock::now();
if (mode == "ref") process_ref(dst, src, kernel);
else if (mode == "morton") process_morton(dst, src, kernel, nbits);
auto t_end = std::chrono::high_resolution_clock::now();
std::cout << "Elapsed time: "
<< std::chrono::duration_cast<std::chrono::microseconds>(t_end - t_start).count()
<< " microseconds" << std::endl;
// Store final image on disk
auto out = ImageOutput::create(filename);
out->open(filename, spec);
dst.write(out.get());
out->close();
return EXIT_SUCCESS;
}
- Ngôn ngữ chính
- C++
- Star
- 2.4k
- Fork
- 718
- Merge trung bình
- 2 ngày 10 giờ
- Pull request đã merge (30 ngày)
- 87
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của AcademySoftwareFoundation/OpenImageIO
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 45/100
AcademySoftwareFoundation/OpenImageIO#5658 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug: deep paste wraps into the next scanline instead of clipping, and ignores chbeginCó thể đã có người làm @lgritz đã nhận 1 ngày trước. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
AcademySoftwareFoundation/OpenImageIO#5649 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug: make_kernel("binomial", ...) indexes its tap arrays past their allocation for even or fractional extentsCó thể đã có người làm @lgritz đã nhận 1 ngày trước. Đang mở
Độ khó 3/5 Nửa ngày Mức phù hợp với người mới 62/100
AcademySoftwareFoundation/OpenImageIO#5648 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
AcademySoftwareFoundation/OpenImageIO#5619 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 10/100
AcademySoftwareFoundation/OpenImageIO#5570 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của AcademySoftwareFoundation/OpenImageIO
Issue tương tự
-
Linux npm packaging leaves workspace files that block subsequent CI checkoutCó thể đã có người làm @Spockkk0225 đã nhận hôm nay. Đang mởci
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 73/100
alibaba/neug#1195 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 3 ngày
-
QA/No release-notes/exclude tests tests/missing-coverage tests/test-quality
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 71/100
brave/brave-browser#61019 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
? - Needs Triage bug CUTLASS C++
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
Maintainer thường phản hồi trong vòng 4 ngày