async io tile_max
This commit is contained in:
parent
1fdd74dc32
commit
c683cbde4d
18
src/tiff_max.py
Normal file
18
src/tiff_max.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import time
|
||||||
|
from osgeo import gdal
|
||||||
|
|
||||||
|
# 打开图像(默认是只读模式)
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
ds = gdal.Open("imgs/ortho.tif", gdal.GA_ReadOnly)
|
||||||
|
if ds is None:
|
||||||
|
raise RuntimeError("Failed to open dataset")
|
||||||
|
|
||||||
|
band = ds.GetRasterBand(1) # 取第一个波段
|
||||||
|
array = band.ReadAsArray() # 整个波段读入内存(同步)
|
||||||
|
max_val = array.max()
|
||||||
|
|
||||||
|
end_time = time.time()
|
||||||
|
|
||||||
|
print(f"GDAL Max: {max_val}")
|
||||||
|
print(f"Time taken: {end_time - start_time:.3f} seconds")
|
98
src/tile_max_reduce.c
Normal file
98
src/tile_max_reduce.c
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <tiffio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
TIFF *tif = TIFFOpen("imgs/ortho.tif", "r");
|
||||||
|
if (!tif)
|
||||||
|
{
|
||||||
|
printf("Failed to open file.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 tileWidth, tileHeight;
|
||||||
|
TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tileWidth);
|
||||||
|
TIFFGetField(tif, TIFFTAG_TILELENGTH, &tileHeight);
|
||||||
|
printf("Tile size: %dx%d\n", tileWidth, tileHeight);
|
||||||
|
|
||||||
|
uint32 imageWidth, imageHeight;
|
||||||
|
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
|
||||||
|
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageHeight);
|
||||||
|
|
||||||
|
uint32 tilesAcross = (imageWidth + tileWidth - 1) / tileWidth;
|
||||||
|
uint32 tilesDown = (imageHeight + tileHeight - 1) / tileHeight;
|
||||||
|
uint32 totalTiles = tilesAcross * tilesDown;
|
||||||
|
printf("Tile count: %d x %d = %d\n", tilesAcross, tilesDown, totalTiles);
|
||||||
|
|
||||||
|
uint16 samplesPerPixel;
|
||||||
|
uint16 bitsPerSample;
|
||||||
|
|
||||||
|
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel);
|
||||||
|
TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
|
||||||
|
|
||||||
|
printf("Samples per pixel: %d\n", samplesPerPixel);
|
||||||
|
printf("Bits per sample: %d\n", bitsPerSample);
|
||||||
|
|
||||||
|
uint16 sampleFormat = SAMPLEFORMAT_UINT;
|
||||||
|
TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sampleFormat);
|
||||||
|
printf("Sample format: %d\n", sampleFormat); // 1=uint, 2=int, 3=float
|
||||||
|
|
||||||
|
tsize_t tileBufSize = TIFFTileSize(tif);
|
||||||
|
if (tileBufSize == 0)
|
||||||
|
{
|
||||||
|
printf("TIFFTileSize returned 0. Possibly not tiled.\n");
|
||||||
|
TIFFClose(tif);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分配一个缓冲区用于存放一个 tile 的像素数据(未压缩)
|
||||||
|
uint8_t *tileBuf = (uint8_t *)_TIFFmalloc(tileBufSize);
|
||||||
|
if (!tileBuf)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to allocate tile buffer.\n");
|
||||||
|
TIFFClose(tif);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局最大值初始化
|
||||||
|
uint8_t globalMax = 0;
|
||||||
|
|
||||||
|
// 遍历每个 tile 并解码为像素数据
|
||||||
|
for (uint32 i = 0; i < totalTiles; i++)
|
||||||
|
{
|
||||||
|
tsize_t readBytes = TIFFReadEncodedTile(tif, i, tileBuf, tileBufSize);
|
||||||
|
if (readBytes == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to decode tile %d\n", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每 tile 最大值初始化
|
||||||
|
uint8_t tileMax = 0;
|
||||||
|
|
||||||
|
// 遍历所有像素(只对第一个波段进行最大值统计)
|
||||||
|
uint32 numPixels = readBytes / samplesPerPixel;
|
||||||
|
for (uint32 px = 0; px < numPixels; px++)
|
||||||
|
{
|
||||||
|
uint8_t value = tileBuf[px * samplesPerPixel]; // 假设只看第1通道
|
||||||
|
if (value > tileMax)
|
||||||
|
tileMax = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印 tile 最大值
|
||||||
|
printf("Tile %3d: Max = %3d\n", i, tileMax);
|
||||||
|
|
||||||
|
// Reduce 更新全局最大值
|
||||||
|
if (tileMax > globalMax)
|
||||||
|
globalMax = tileMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n>>> Global Max Value = %d\n", globalMax);
|
||||||
|
|
||||||
|
_TIFFfree(tileBuf);
|
||||||
|
TIFFClose(tif);
|
||||||
|
return 0;
|
||||||
|
}
|
152
src/tile_max_reduce_io_uring.c
Normal file
152
src/tile_max_reduce_io_uring.c
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
// tile_max_reduce_uring_timed.c
|
||||||
|
#define _POSIX_C_SOURCE 199309L
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <liburing.h>
|
||||||
|
#include <tiffio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define MAX_TILES 2048
|
||||||
|
|
||||||
|
// 获取当前时间(秒 + 纳秒)函数
|
||||||
|
static double get_time_sec()
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
return ts.tv_sec + ts.tv_nsec * 1e-9;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
const char *filepath = "imgs/ortho.tif";
|
||||||
|
|
||||||
|
int fd = open(filepath, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
perror("open");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TIFF *tif = TIFFOpen(filepath, "r");
|
||||||
|
if (!tif)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to open TIFF with libtiff.\n");
|
||||||
|
close(fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 tileWidth, tileHeight, imageWidth, imageHeight;
|
||||||
|
TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tileWidth);
|
||||||
|
TIFFGetField(tif, TIFFTAG_TILELENGTH, &tileHeight);
|
||||||
|
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
|
||||||
|
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageHeight);
|
||||||
|
|
||||||
|
uint32 tilesAcross = (imageWidth + tileWidth - 1) / tileWidth;
|
||||||
|
uint32 tilesDown = (imageHeight + tileHeight - 1) / tileHeight;
|
||||||
|
uint32 totalTiles = tilesAcross * tilesDown;
|
||||||
|
|
||||||
|
if (totalTiles > MAX_TILES)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Too many tiles: %u (limit %d)\n", totalTiles, MAX_TILES);
|
||||||
|
TIFFClose(tif);
|
||||||
|
close(fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tsize_t *byteCounts = NULL;
|
||||||
|
toff_t *offsets = NULL;
|
||||||
|
|
||||||
|
TIFFGetField(tif, TIFFTAG_TILEBYTECOUNTS, &byteCounts);
|
||||||
|
TIFFGetField(tif, TIFFTAG_TILEOFFSETS, &offsets);
|
||||||
|
|
||||||
|
// 初始化 io_uring
|
||||||
|
struct io_uring ring;
|
||||||
|
io_uring_queue_init(totalTiles, &ring, 0);
|
||||||
|
|
||||||
|
// 内存 buffer
|
||||||
|
char *buffers[MAX_TILES];
|
||||||
|
uint8_t tileMaxes[MAX_TILES]; // 每 tile 最大值
|
||||||
|
|
||||||
|
// 记录异步读取 + tile max 计算开始时间
|
||||||
|
double t_start = get_time_sec();
|
||||||
|
|
||||||
|
// 提交读请求
|
||||||
|
for (uint32 i = 0; i < totalTiles; i++)
|
||||||
|
{
|
||||||
|
buffers[i] = malloc(byteCounts[i]);
|
||||||
|
if (!buffers[i])
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to alloc buffer for tile %u\n", i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
|
||||||
|
io_uring_prep_read(sqe, fd, buffers[i], byteCounts[i], offsets[i]);
|
||||||
|
io_uring_sqe_set_data(sqe, buffers[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
io_uring_submit(&ring);
|
||||||
|
|
||||||
|
// 等待结果 & 计算每 tile max
|
||||||
|
for (uint32 i = 0; i < totalTiles; i++)
|
||||||
|
{
|
||||||
|
struct io_uring_cqe *cqe;
|
||||||
|
int ret = io_uring_wait_cqe(&ring, &cqe);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "wait_cqe failed: %d\n", ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *data = io_uring_cqe_get_data(cqe);
|
||||||
|
int len = cqe->res;
|
||||||
|
|
||||||
|
uint8_t maxVal = 0;
|
||||||
|
for (int j = 0; j < len; j++)
|
||||||
|
{
|
||||||
|
uint8_t val = (uint8_t)data[j];
|
||||||
|
if (val > maxVal)
|
||||||
|
maxVal = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
tileMaxes[i] = maxVal;
|
||||||
|
printf("Tile %3u: Max = %3u\n", i, maxVal);
|
||||||
|
|
||||||
|
io_uring_cqe_seen(&ring, cqe);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t_io_calc_end = get_time_sec();
|
||||||
|
|
||||||
|
// reduce 求全局最大值,单独计时
|
||||||
|
uint8_t globalMax = 0;
|
||||||
|
|
||||||
|
double t_reduce_start = get_time_sec();
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < totalTiles; i++)
|
||||||
|
{
|
||||||
|
if (tileMaxes[i] > globalMax)
|
||||||
|
globalMax = tileMaxes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
double t_reduce_end = get_time_sec();
|
||||||
|
|
||||||
|
printf("\n>>> Global Max Value: %d\n", globalMax);
|
||||||
|
printf("Time: Async IO + tile max calculation = %.6f seconds\n", t_io_calc_end - t_start);
|
||||||
|
printf("Time: Reduce global max = %.6f seconds\n", t_reduce_end - t_reduce_start);
|
||||||
|
|
||||||
|
// 清理
|
||||||
|
for (uint32 i = 0; i < totalTiles; i++)
|
||||||
|
{
|
||||||
|
free(buffers[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
io_uring_queue_exit(&ring);
|
||||||
|
TIFFClose(tif);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user