fix sever L4 errors
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// file="L4.InternalOp"
|
// file="L4.Evict"
|
||||||
// Project: StgSharp
|
// Project: StgSharp
|
||||||
// AuthorGroup: Nitload
|
// AuthorGroup: Nitload Space
|
||||||
// Copyright (c) Nitload. All rights reserved.
|
// Copyright (c) Nitload Space. All rights reserved.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -54,10 +54,17 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="count">
|
||||||
|
///
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// Count of lines not evicted
|
||||||
|
/// </returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private unsafe void Evict(
|
private unsafe int Evict(int count = 1)
|
||||||
int count = 1
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
int remain = count;
|
int remain = count;
|
||||||
Vector128<byte> one = Vector128.Create((byte)0x01);
|
Vector128<byte> one = Vector128.Create((byte)0x01);
|
||||||
@@ -77,32 +84,30 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
{
|
{
|
||||||
// EvictLine(i + index);
|
// EvictLine(i + index);
|
||||||
_ = _map.TryRemove(head->_origin, out _);
|
_ = _map.TryRemove(head->_origin, out _);
|
||||||
|
PrefetchPredict.WriteBack(head->_address, head->_profile, new ReadOnlySpan<byte>((byte*)head->_address, Unsafe.SizeOf<CacheLineData>()));
|
||||||
RecycleLine(index);
|
RecycleLine(index);
|
||||||
remain--;
|
remain--;
|
||||||
}
|
}
|
||||||
evictMask &= evictMask - 1;
|
evictMask &= evictMask - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return remain;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void RecycleLine(
|
private void RecycleLine(int id)
|
||||||
int id
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
_idMux.Push(id);
|
_idMux.Push(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private bool TryGetEmptyLine(
|
private bool TryGetEmptyLine(out int index)
|
||||||
out int index
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (_idMux.TryPop(out index)) {
|
if (_idMux.TryPop(out index)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
index = _maxId;
|
index = _maxId;
|
||||||
return Interlocked.Increment(ref _maxId) >= CacheLineCount;
|
return Interlocked.Increment(ref _maxId) <= CacheLineCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,11 +36,50 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
public interface IPrefetchPredict
|
public interface IPrefetchPredict
|
||||||
{
|
{
|
||||||
|
|
||||||
int Predict(Span<CacheLinePrediction> node);
|
/// <summary>
|
||||||
|
/// Writes predicted cache line descriptors into <paramref name="node" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node">
|
||||||
|
/// Prediction output buffer.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="count">
|
||||||
|
/// When this method returns, contains the number of valid entries written to <paramref
|
||||||
|
/// name="node" />. The value must not exceed <paramref name="node" />.Length.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if any prediction data was produced; otherwise, <see langword="false"
|
||||||
|
/// />.
|
||||||
|
/// </returns>
|
||||||
|
bool Predict(Span<CacheLinePrediction> node, out int count);
|
||||||
|
|
||||||
bool Prefetch(nuint origin, ulong policy, nuint cache);
|
/// <summary>
|
||||||
|
/// Materializes the cache line identified by <paramref name="origin" /> into <paramref
|
||||||
|
/// name="cache" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="origin">
|
||||||
|
/// Source address associated with the cache line.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="policy">
|
||||||
|
/// Mapping policy associated with the cache line.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="cache">
|
||||||
|
/// Destination cache line buffer.
|
||||||
|
/// </param>
|
||||||
|
void Prefetch(nuint origin, ulong policy, Span<byte> cache);
|
||||||
|
|
||||||
void WriteBack(nuint origin, ulong policy, nuint cache);
|
/// <summary>
|
||||||
|
/// Writes the cache line in <paramref name="cache" /> back to <paramref name="origin" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="origin">
|
||||||
|
/// Source address associated with the cache line.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="policy">
|
||||||
|
/// Mapping policy associated with the cache line.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="cache">
|
||||||
|
/// Source cache line buffer.
|
||||||
|
/// </param>
|
||||||
|
void WriteBack(nuint origin, ulong policy, ReadOnlySpan<byte> cache);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// file="L4.Prefetch"
|
// file="L4.Prefetch"
|
||||||
// Project: StgSharp
|
// Project: StgSharp
|
||||||
// AuthorGroup: Nitload
|
// AuthorGroup: Nitload Space
|
||||||
// Copyright (c) Nitload. All rights reserved.
|
// Copyright (c) Nitload Space. All rights reserved.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -25,18 +25,27 @@
|
|||||||
//
|
//
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
namespace StgSharp.HighPerformance.Memory
|
namespace StgSharp.HighPerformance.Memory
|
||||||
{
|
{
|
||||||
public unsafe partial class L4
|
public unsafe partial class L4
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public const int MaxActivateCacheLineCount = 1024;
|
||||||
|
|
||||||
private partial void Prefetch()
|
private partial void Prefetch()
|
||||||
{
|
{
|
||||||
if (PrefetchPredict is null) {
|
if (PrefetchPredict is null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (_activeCount > MaxActivateCacheLineCount) {
|
||||||
|
throw new OverflowException("Too many activated cache line in external reference.");
|
||||||
|
}
|
||||||
Span<CacheLinePrediction> span = new(_prediction, PredictionCount);
|
Span<CacheLinePrediction> span = new(_prediction, PredictionCount);
|
||||||
int actualCount = PrefetchPredict.Predict(span);
|
if (!(PrefetchPredict.Predict(span, out int actualCount) && actualCount > 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int missIndex = 0;
|
int missIndex = 0;
|
||||||
AgeAll();
|
AgeAll();
|
||||||
for (int i = 0; i < actualCount; i++)
|
for (int i = 0; i < actualCount; i++)
|
||||||
@@ -61,21 +70,31 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 未经初始化的_idMux可能会导致TryGetEmptyLine失败,导致无法预取,最好添加末尾指针计数
|
int retryCount = 0, index, remain = missIndex - i;
|
||||||
if (!TryGetEmptyLine(out int index))
|
const int maxRetry = 1024;
|
||||||
|
while (!TryGetEmptyLine(out index))
|
||||||
{
|
{
|
||||||
throw new OverflowException("L4 has no empty cache line.");
|
missIndex = Evict(missIndex);
|
||||||
|
retryCount++;
|
||||||
|
if (retryCount > maxRetry) {
|
||||||
|
throw new OverflowException($"Failed to evict cache line after {maxRetry} retries.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CacheLineHead* head = &_head[index];
|
CacheLineHead* head = &_head[index];
|
||||||
|
head->_id = index;
|
||||||
|
head->_origin = address;
|
||||||
|
head->_profile = handle.MapPolicy;
|
||||||
|
head->_refCount = 0;
|
||||||
|
head->_address = (nuint)(&_data[index]);
|
||||||
|
|
||||||
// pre fetch them here
|
// pre fetch them here
|
||||||
_ = PrefetchPredict.Prefetch(head->_origin, head->_profile, head->_address);
|
PrefetchPredict.Prefetch(head->_origin, head->_profile, new Span<byte>((byte*)head->_address, Unsafe.SizeOf<CacheLineData>()));
|
||||||
|
_ = _map.TryAddOrSet(address, (nuint)head, out _);
|
||||||
}
|
}
|
||||||
|
_ = Interlocked.Add(ref _aheadCount, actualCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private partial bool TestHit(
|
private partial bool TestHit(nuint origin)
|
||||||
nuint origin
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (_map.TryGet(origin, out nuint handle))
|
if (_map.TryGet(origin, out nuint handle))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// file="L4"
|
// file="L4"
|
||||||
// Project: StgSharp
|
// Project: StgSharp
|
||||||
// AuthorGroup: Nitload
|
// AuthorGroup: Nitload Space
|
||||||
// Copyright (c) Nitload. All rights reserved.
|
// Copyright (c) Nitload Space. All rights reserved.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -108,31 +108,24 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public CacheLine Map(
|
public CacheLine Map(nuint origin)
|
||||||
nuint origin
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (_aheadCount < PredictionLeastAhead)
|
if (_aheadCount < PredictionLeastAhead)
|
||||||
{
|
{
|
||||||
while (true)
|
if (Interlocked.CompareExchange(ref _prefetching, 1, 0) == 0)
|
||||||
{
|
{
|
||||||
if (Interlocked.CompareExchange(ref _prefetching, 1, 0) == 0)
|
try
|
||||||
{
|
{
|
||||||
try
|
if (_aheadCount < PredictionLeastAhead)
|
||||||
{
|
{
|
||||||
if (_aheadCount < PredictionLeastAhead)
|
// do prefetch in work load now, sync
|
||||||
{
|
Prefetch();
|
||||||
// do prefetch in work load now, sync
|
|
||||||
Prefetch();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_prefetching = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Thread.Sleep(0);
|
finally
|
||||||
|
{
|
||||||
|
_prefetching = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (true)
|
while (true)
|
||||||
@@ -145,6 +138,7 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
{
|
{
|
||||||
(*_eviction)[entry->_id] = 0;
|
(*_eviction)[entry->_id] = 0;
|
||||||
_ = Interlocked.Increment(ref _activeCount);
|
_ = Interlocked.Increment(ref _activeCount);
|
||||||
|
_ = Interlocked.Decrement(ref _aheadCount);
|
||||||
return new CacheLine(entry->_address, ref _activeCount, ref entry->_refCount);
|
return new CacheLine(entry->_address, ref _activeCount, ref entry->_refCount);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
@@ -157,9 +151,7 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
|
|
||||||
private partial void Prefetch();
|
private partial void Prefetch();
|
||||||
|
|
||||||
private partial bool TestHit(
|
private partial bool TestHit(nuint origin);
|
||||||
nuint origin
|
|
||||||
);
|
|
||||||
|
|
||||||
public ref struct CacheLine : IDisposable
|
public ref struct CacheLine : IDisposable
|
||||||
{
|
{
|
||||||
@@ -168,11 +160,7 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
private ref int _refCount;
|
private ref int _refCount;
|
||||||
private nuint _handle;
|
private nuint _handle;
|
||||||
|
|
||||||
internal CacheLine(
|
internal CacheLine(nuint handle, ref int activeCount, ref int cacheRefCount)
|
||||||
nuint handle,
|
|
||||||
ref int activeCount,
|
|
||||||
ref int cacheRefCount
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
_handle = handle;
|
_handle = handle;
|
||||||
_refCount = ref cacheRefCount;
|
_refCount = ref cacheRefCount;
|
||||||
|
|||||||
Reference in New Issue
Block a user