优化红外图像性能,改回double存储
This commit is contained in:
parent
eb3647a8f6
commit
3eab373226
@ -170,8 +170,8 @@ namespace ThreatSource.Tests.Simulation
|
||||
//string[] missileTypes = ["lsgm_001"];
|
||||
//string[] missileTypes = ["lbr_001"];
|
||||
//string[] missileTypes = ["irc_001"];
|
||||
//string[] missileTypes = ["itg_001"];
|
||||
string[] missileTypes = ["mmw_001"];
|
||||
string[] missileTypes = ["itg_001"];
|
||||
//string[] missileTypes = ["mmw_001"];
|
||||
//string[] missileTypes = ["tsm_001"];
|
||||
|
||||
string missileType = missileTypes[Random.Shared.Next(missileTypes.Length)];
|
||||
|
||||
@ -9,7 +9,7 @@ namespace ThreatSource.Guidance
|
||||
/// 该类存储红外图像的基本信息:
|
||||
/// - 图像尺寸
|
||||
/// - 像素物理大小
|
||||
/// - 红外强度矩阵(使用byte存储,对数缩放)
|
||||
/// - 红外强度矩阵
|
||||
/// 用于目标探测和识别
|
||||
/// </remarks>
|
||||
/// <remarks>
|
||||
@ -17,79 +17,6 @@ namespace ThreatSource.Guidance
|
||||
/// </remarks>
|
||||
public class InfraredImage
|
||||
{
|
||||
// === 对数缩放参数 ===
|
||||
/// <summary>
|
||||
/// 强度值的最小值,单位:W/sr
|
||||
/// 默认值1e-6 W/sr,对应约273K(0°C)的物体在合理距离下的辐射强度
|
||||
/// </summary>
|
||||
private const double MIN_INTENSITY = 1e-6;
|
||||
|
||||
/// <summary>
|
||||
/// 强度值的最大值,单位:W/sr
|
||||
/// 默认值1e3 W/sr 对应高温物体在近距离的辐射强度上限
|
||||
/// </summary>
|
||||
private const double MAX_INTENSITY = 1e3;
|
||||
|
||||
/// <summary>
|
||||
/// 最小强度值的对数(log10)
|
||||
/// </summary>
|
||||
private static readonly double MIN_LOG = Math.Log10(MIN_INTENSITY);
|
||||
|
||||
/// <summary>
|
||||
/// 最大强度值的对数(log10)
|
||||
/// </summary>
|
||||
private static readonly double MAX_LOG = Math.Log10(MAX_INTENSITY);
|
||||
|
||||
/// <summary>
|
||||
/// 对数范围
|
||||
/// </summary>
|
||||
private static readonly double LOG_RANGE = MAX_LOG - MIN_LOG;
|
||||
|
||||
/// <summary>
|
||||
/// 预计算的强度值查找表,避免重复的对数运算
|
||||
/// 索引0-255对应byte值,值为对应的强度值(W/sr)
|
||||
/// </summary>
|
||||
private static readonly double[] INTENSITY_LOOKUP_TABLE = new double[256];
|
||||
|
||||
/// <summary>
|
||||
/// 反向查找表:强度值到byte的快速映射
|
||||
/// 使用分段线性插值优化SetIntensity性能
|
||||
/// </summary>
|
||||
private static readonly double[] SORTED_INTENSITY_VALUES = new double[256];
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 静态构造函数,初始化查找表
|
||||
/// </summary>
|
||||
static InfraredImage()
|
||||
{
|
||||
// 预计算所有可能的byte值对应的强度值
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
INTENSITY_LOOKUP_TABLE[i] = ComputeIntensityFromByte((byte)i);
|
||||
SORTED_INTENSITY_VALUES[i] = INTENSITY_LOOKUP_TABLE[i];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算byte值对应的强度值(仅在静态构造函数中使用)
|
||||
/// </summary>
|
||||
/// <param name="byteValue">byte值</param>
|
||||
/// <returns>强度值,单位:W/sr</returns>
|
||||
private static double ComputeIntensityFromByte(byte byteValue)
|
||||
{
|
||||
// 处理零值
|
||||
if (byteValue == 0)
|
||||
return 0.0;
|
||||
|
||||
// 反向对数缩放
|
||||
double normalizedLog = (byteValue - 1) / 254.0;
|
||||
double logIntensity = MIN_LOG + normalizedLog * LOG_RANGE;
|
||||
return Math.Pow(10, logIntensity);
|
||||
}
|
||||
|
||||
// === 基本属性 ===
|
||||
/// <summary>
|
||||
/// 图像宽度,单位:像素
|
||||
/// </summary>
|
||||
@ -106,10 +33,10 @@ namespace ThreatSource.Guidance
|
||||
public double PixelSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 红外强度矩阵,使用byte存储(对数缩放)
|
||||
/// 0 = 零强度,1-255 = 对数缩放的强度值
|
||||
/// 红外强度矩阵
|
||||
/// 单位:W/sr
|
||||
/// </summary>
|
||||
private byte[,] intensityData;
|
||||
private double[,] intensityData;
|
||||
|
||||
/// <summary>
|
||||
/// 图像中心视线方向
|
||||
@ -135,7 +62,7 @@ namespace ThreatSource.Guidance
|
||||
Height = height;
|
||||
PixelSize = pixelSize;
|
||||
LineOfSight = lineOfSight;
|
||||
intensityData = new byte[height, width];
|
||||
intensityData = new double[height, width];
|
||||
SmokeCoverageMask = smokeCoverageMask ?? new bool[height, width];
|
||||
}
|
||||
|
||||
@ -158,7 +85,7 @@ namespace ThreatSource.Guidance
|
||||
// 重新分配强度数据数组(如果尺寸不匹配)
|
||||
if (intensityData == null || intensityData.GetLength(0) != height || intensityData.GetLength(1) != width)
|
||||
{
|
||||
intensityData = new byte[height, width];
|
||||
intensityData = new double[height, width];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -177,12 +104,12 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
if (row >= 0 && row < Height && col >= 0 && col < Width)
|
||||
{
|
||||
intensityData[row, col] = ConvertToByte(value);
|
||||
intensityData[row, col] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取像素强度值(使用预计算查找表,高性能)
|
||||
/// 获取像素强度值
|
||||
/// </summary>
|
||||
/// <param name="row">行索引</param>
|
||||
/// <param name="col">列索引</param>
|
||||
@ -191,74 +118,29 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
if (row >= 0 && row < Height && col >= 0 && col < Width)
|
||||
{
|
||||
return INTENSITY_LOOKUP_TABLE[intensityData[row, col]];
|
||||
return intensityData[row, col];
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将强度值转换为byte(简化版本,高性能)
|
||||
/// </summary>
|
||||
/// <param name="intensity">强度值,单位:W/sr</param>
|
||||
/// <returns>缩放后的byte值</returns>
|
||||
private static byte ConvertToByte(double intensity)
|
||||
{
|
||||
// 处理零值和负值
|
||||
if (intensity <= 0)
|
||||
return 0;
|
||||
|
||||
// 处理超出范围的值
|
||||
if (intensity <= SORTED_INTENSITY_VALUES[1])
|
||||
return 1;
|
||||
if (intensity >= SORTED_INTENSITY_VALUES[255])
|
||||
return 255;
|
||||
|
||||
// 使用简化的二分查找
|
||||
return SimpleBinarySearch(intensity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 简化的二分查找,直接返回最接近的索引(移除距离计算)
|
||||
/// </summary>
|
||||
private static byte SimpleBinarySearch(double intensity)
|
||||
{
|
||||
int left = 1;
|
||||
int right = 255;
|
||||
|
||||
// 标准二分查找
|
||||
while (left < right)
|
||||
{
|
||||
int mid = (left + right) >> 1; // 使用位移代替除法
|
||||
if (SORTED_INTENSITY_VALUES[mid] < intensity)
|
||||
left = mid + 1;
|
||||
else
|
||||
right = mid;
|
||||
}
|
||||
|
||||
return (byte)left;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取内存占用信息(用于性能监控)
|
||||
/// </summary>
|
||||
/// <returns>内存占用字节数</returns>
|
||||
public long GetMemoryUsage()
|
||||
{
|
||||
return sizeof(byte) * Width * Height; // byte数组
|
||||
return sizeof(double) * Width * Height; // double数组
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取缩放参数信息(用于调试)
|
||||
/// 获取图像信息(用于调试)
|
||||
/// </summary>
|
||||
/// <returns>缩放参数的调试信息</returns>
|
||||
public string GetScalingInfo()
|
||||
/// <returns>图像的调试信息</returns>
|
||||
public string GetImageInfo()
|
||||
{
|
||||
return $"强度范围: [{MIN_INTENSITY:E3}, {MAX_INTENSITY:E3}] W/sr, " +
|
||||
$"对数范围: [{MIN_LOG:F1}, {MAX_LOG:F1}], " +
|
||||
$"相对精度: ~4.3%, " +
|
||||
$"内存占用: {GetMemoryUsage():N0} bytes, " +
|
||||
$"查找表: {INTENSITY_LOOKUP_TABLE.Length * sizeof(double):N0} bytes, " +
|
||||
$"算法: 简化二分查找";
|
||||
return $"图像尺寸: {Width}x{Height}, " +
|
||||
$"像素大小: {PixelSize:E3} 弧度/像素, " +
|
||||
$"内存占用: {GetMemoryUsage():N0} bytes";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -32,7 +32,7 @@ dotnet test --filter "Category!=Performance"
|
||||
|
||||
6. 仅运行性能测试:
|
||||
```bash
|
||||
dotnet test --filter "Category=Performance"
|
||||
dotnet test --filter "Category=Performance" --logger "console;verbosity=detailed"
|
||||
```
|
||||
|
||||
7. 按类名排除:
|
||||
@ -45,6 +45,11 @@ dotnet test --filter "FullyQualifiedName!~PerformanceTest"
|
||||
dotnet test --filter "Category!=Performance&FullyQualifiedName!~Performance"
|
||||
```
|
||||
|
||||
9. 运行 Release 模式下的性能测试:
|
||||
```bash
|
||||
dotnet test --configuration Release --filter "RunPerformanceTest" --verbosity minimal --nologo --logger "console;verbosity=normal"
|
||||
```
|
||||
|
||||
### 测试报告
|
||||
时间:2025-05-16
|
||||
测试目的:测试 Vector3D 作为类和结构体的性能差异
|
||||
|
||||
@ -200,7 +200,7 @@ dotnet test --configuration Release --filter "RunPerformanceTest" --verbosity mi
|
||||
- 优化效果:
|
||||
- GC次数减少 60%,效果不错,但帧时间有所上升
|
||||
|
||||
- 是否采用:是
|
||||
- 是否采用:否,考虑提高了程序复杂度,提高了帧时间
|
||||
|
||||
=== 详细性能测试结果 ===
|
||||
|
||||
@ -284,7 +284,7 @@ dotnet test --configuration Release --filter "RunPerformanceTest" --verbosity mi
|
||||
- 优化效果:
|
||||
- 没有什么变化
|
||||
|
||||
- 是否采用:是,考虑将Intensity从对数运算改为查找表
|
||||
- 是否采用:否,考虑提高了程序复杂度,提高了帧时间
|
||||
|
||||
=== 详细性能测试结果 ===
|
||||
|
||||
@ -407,4 +407,45 @@ Gen2 GC次数: 0 (0.0 次/秒)
|
||||
帧时间表现: 优秀 ✅
|
||||
内存管理: 优秀 ✅
|
||||
GC频率: 优秀 ✅
|
||||
【潜在问题分析】
|
||||
【潜在问题分析】
|
||||
|
||||
### 第八次优化
|
||||
|
||||
时间:2025-06-05 12:00:00
|
||||
|
||||
- 优化内容:
|
||||
- 将 InfraredImage 的 Intensity 数组从 byte 改回 double,去掉对数计算和查找表
|
||||
|
||||
- 优化效果:
|
||||
- 帧时间减小,GC次数增加,但影响不大
|
||||
|
||||
- 是否采用:是
|
||||
|
||||
=== 详细性能测试结果 ===
|
||||
【基本统计】
|
||||
测试时长: 30.0 秒
|
||||
总更新次数: 1416
|
||||
平均FPS: 47.2
|
||||
平均帧时间: 1.10 ms
|
||||
【帧时间分析】
|
||||
最小帧时间: 0.00 ms
|
||||
最大帧时间: 19.10 ms
|
||||
95%分位数: 5.03 ms
|
||||
99%分位数: 7.89 ms
|
||||
【内存使用分析】
|
||||
起始内存: 2.93 MB
|
||||
结束内存: 8.54 MB
|
||||
峰值内存: 9.52 MB
|
||||
内存增长: 5.61 MB
|
||||
平均内存增长率: 0.19 MB/s
|
||||
【垃圾回收分析】
|
||||
Gen0 GC次数: 93 (3.1 次/秒)
|
||||
Gen1 GC次数: 79 (2.6 次/秒)
|
||||
Gen2 GC次数: 69 (2.3 次/秒)
|
||||
总GC次数: 241
|
||||
【性能评级】
|
||||
帧时间表现: 优秀 ✅
|
||||
内存管理: 优秀 ✅
|
||||
GC频率: 一般 ⚠️
|
||||
【潜在问题分析】
|
||||
⚠️ Gen0 GC频率过高,存在内存分配风暴
|
||||
Loading…
Reference in New Issue
Block a user