matrix thread pool use ParaWaveFront and heavy sync

This commit is contained in:
Youmu Liu
2026-04-26 17:38:10 +08:00
parent 251762791e
commit ecb1f04770
7 changed files with 152 additions and 131 deletions
@@ -1,30 +1,27 @@
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// file="NotEnumerableList.cs" // file="LinearBag"
// Project: StgSharp // Project: StgSharp
// AuthorGroup: Nitload Space // AuthorGroup: Nitload
// Copyright (c) Nitload Space. All rights reserved. // Copyright (c) Nitload. All rights reserved.
// //
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person obtaining a copy
// obtaining a copy of this software and associated documentation // of this software and associated documentation files (the "Software"), to deal
// files (the “Software”), to deal in the Software without restriction, // in the Software without restriction, including without limitation the rights
// including without limitation the rights to use, copy, modify, merge, // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// publish, distribute, sublicense, and/or sell copies of the Software, // copies of the Software, and to permit persons to whom the Software is
// and to permit persons to whom the Software is furnished to do so, // furnished to do so, subject to the following conditions:
// subject to the following conditions: //
// // The above copyright notice and this permission notice shall be included in all
// The above copyright notice and // copies or substantial portions of the Software.
// this permission notice shall be included in all copies //
// or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// THE SOFTWARE IS PROVIDED “AS IS”, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // SOFTWARE.
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// //
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -41,7 +38,9 @@ namespace StgSharp.Collections
/// Build a <see cref="LinearBag{T}" /> from a read-only span. Capacity will exactly fit /// Build a <see cref="LinearBag{T}" /> from a read-only span. Capacity will exactly fit
/// the input. /// the input.
/// </summary> /// </summary>
public static LinearBag<T> FromSpan<T>(ReadOnlySpan<T> values) public static LinearBag<T> Create<T>(
ReadOnlySpan<T> values
)
{ {
if (values.IsEmpty) { if (values.IsEmpty) {
return new LinearBag<T>(4); return new LinearBag<T>(4);
@@ -63,8 +62,10 @@ namespace StgSharp.Collections
/// <typeparam name="T"> /// <typeparam name="T">
/// Element type. /// Element type.
/// </typeparam> /// </typeparam>
[CollectionBuilder(typeof(LinearBagBuilder), nameof(LinearBagBuilder.FromSpan))] [CollectionBuilder(typeof(LinearBagBuilder), nameof(LinearBagBuilder.Create))]
public class LinearBag<T>(int capacity = 4) public class LinearBag<T>(
int capacity = 4
)
{ {
// Invariant: valid elements occupy indexes [0, Count-1]. Count is the number of live elements. // Invariant: valid elements occupy indexes [0, Count-1]. Count is the number of live elements.
@@ -73,17 +74,20 @@ namespace StgSharp.Collections
/// <summary> /// <summary>
/// Access element by index (0..Count-1). Throws if out of range. /// Access element by index (0..Count-1). Throws if out of range.
/// </summary> /// </summary>
public T this[int index] public T this[
int index
]
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (uint)index >= (uint)Count ? throw new ArgumentOutOfRangeException(nameof(index)) : _items[index]; get
{
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, Count);
return _items[index];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
set set
{ {
if ((uint)index >= (uint)Count) { ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, Count);
throw new ArgumentOutOfRangeException(nameof(index));
}
_items[index] = value; _items[index] = value;
} }
} }
@@ -102,7 +106,9 @@ namespace StgSharp.Collections
/// Adds an item (unordered). Expands internal array if needed. /// Adds an item (unordered). Expands internal array if needed.
/// </summary> /// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(T item) public void Add(
T item
)
{ {
if (Count == _items.Length) { if (Count == _items.Length) {
EnsureCapacity(Count + 1); EnsureCapacity(Count + 1);
@@ -144,7 +150,9 @@ namespace StgSharp.Collections
/// <summary> /// <summary>
/// Removes the first occurrence of value (unordered). Does nothing if not found. /// Removes the first occurrence of value (unordered). Does nothing if not found.
/// </summary> /// </summary>
public void Remove(T value) public void Remove(
T value
)
{ {
EqualityComparer<T> comparer = EqualityComparer<T>.Default; EqualityComparer<T> comparer = EqualityComparer<T>.Default;
for (int i = 0; i < Count; i++) for (int i = 0; i < Count; i++)
@@ -162,7 +170,9 @@ namespace StgSharp.Collections
/// last). Preserves O(1) removal at cost of ordering. /// last). Preserves O(1) removal at cost of ordering.
/// </summary> /// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveAt(int index) public void RemoveAt(
int index
)
{ {
if ((uint)index >= (uint)Count) { if ((uint)index >= (uint)Count) {
throw new ArgumentOutOfRangeException(nameof(index)); throw new ArgumentOutOfRangeException(nameof(index));
@@ -181,13 +191,15 @@ namespace StgSharp.Collections
/// Ensures capacity is at least <paramref name="min" />. Doubles size when growing. /// Ensures capacity is at least <paramref name="min" />. Doubles size when growing.
/// </summary> /// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void EnsureCapacity(int min) private void EnsureCapacity(
int min
)
{ {
if (_items.Length >= min) { if (_items.Length >= min) {
return; return;
} }
int newCapacity = _items.Length == 0 ? 4 : _items.Length * 2; int newCapacity = (_items.Length == 0) ? 4 : (_items.Length * 2);
if (newCapacity < min) { if (newCapacity < min) {
newCapacity = min; newCapacity = min;
} }
@@ -1,30 +1,27 @@
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// file="MatrixOperatorPolicy.cs" // file="MatrixOperatorPolicy"
// Project: StgSharp // Project: StgSharp
// AuthorGroup: Nitload Space // AuthorGroup: Nitload
// Copyright (c) Nitload Space. All rights reserved. // Copyright (c) Nitload. All rights reserved.
// //
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person obtaining a copy
// obtaining a copy of this software and associated documentation // of this software and associated documentation files (the "Software"), to deal
// files (the “Software”), to deal in the Software without restriction, // in the Software without restriction, including without limitation the rights
// including without limitation the rights to use, copy, modify, merge, // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// publish, distribute, sublicense, and/or sell copies of the Software, // copies of the Software, and to permit persons to whom the Software is
// and to permit persons to whom the Software is furnished to do so, // furnished to do so, subject to the following conditions:
// subject to the following conditions: //
// // The above copyright notice and this permission notice shall be included in all
// The above copyright notice and // copies or substantial portions of the Software.
// this permission notice shall be included in all copies //
// or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// THE SOFTWARE IS PROVIDED “AS IS”, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // SOFTWARE.
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// //
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -36,7 +33,7 @@ using System.Threading.Tasks;
namespace StgSharp.Mathematics.Numeric.Runtime namespace StgSharp.Mathematics.Numeric.Runtime
{ {
internal enum MatrixCachePolicy internal enum MatrixCachePolicy : short
{ {
None = 0, None = 0,
@@ -25,6 +25,7 @@
// //
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
using StgSharp.Collections;
using StgSharp.HighPerformance.Memory; using StgSharp.HighPerformance.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -41,7 +42,8 @@ namespace StgSharp.Mathematics.Numeric
private static NumaMeasurement[] _numaMeasurements; private static NumaMeasurement[] _numaMeasurements;
private static int[] _numaPayload; private static int[] _numaPayload;
private static MatrixParallelThread[][] _numaThreads; private static LinearBag<MatrixParallelThread>[] _numaSyncHeavy;
private static LinearBag<MatrixParallelThread>[] _numaWaveFront;
private static MatrixParallelThread[] _threads; private static MatrixParallelThread[] _threads;
private static void UpdateThreadPayload() private static void UpdateThreadPayload()
@@ -65,12 +65,12 @@ namespace StgSharp.Mathematics.Numeric
ulong additionalPayload = 0; ulong additionalPayload = 0;
for (int i = 0; i < _numaMeasurements.Length; i++) for (int i = 0; i < _numaMeasurements.Length; i++)
{ {
MatrixParallelThread[] numa = _numaThreads[i]; MatrixParallelThread[] numa = _numaWaveFront[i];
if ((numa is null) || (numa.Length == 0)) if ((numa is null) || (numa.Length == 0))
{ {
continue; continue;
} }
ulong total = (ulong)_numaThreads[i].Length; ulong total = (ulong)_numaWaveFront[i].Length;
NumaMeasurement measure = _numaMeasurements[i]; NumaMeasurement measure = _numaMeasurements[i];
ulong numaPayload = measure.ActiveTasks; ulong numaPayload = measure.ActiveTasks;
uint numaActive = measure.ActiveThreadCount; uint numaActive = measure.ActiveThreadCount;
@@ -82,7 +82,7 @@ namespace StgSharp.Mathematics.Numeric
} }
} }
L4 cache = _numaBuffer[payloadIndex]; L4 cache = _numaBuffer[payloadIndex];
MatrixParallelThread[] selectedNuma = _numaThreads[payloadIndex]; MatrixParallelThread[] selectedNuma = _numaWaveFront[payloadIndex];
throw new NotImplementedException(); throw new NotImplementedException();
} }
@@ -84,7 +84,7 @@ namespace StgSharp.Mathematics.Numeric
_retiredThreads = new(RESERVED_THREAD_COUNT); _retiredThreads = new(RESERVED_THREAD_COUNT);
// init thread on all logical cores // init thread on all logical cores
_numaThreads = Numa.CreateForeachThread<MatrixParallelThread>( MatrixParallelThread[][] numaWaveOrigin = Numa.CreateForeachThread<MatrixParallelThread>(
core => { core => {
MatrixParallelThread thread = new(core); MatrixParallelThread thread = new(core);
SpinWait.SpinUntil(() => thread.State == MatrixThreadState.Ready); SpinWait.SpinUntil(() => thread.State == MatrixThreadState.Ready);
@@ -108,15 +108,15 @@ namespace StgSharp.Mathematics.Numeric
// retire threads // retire threads
if (ContextCount == 1) if (ContextCount == 1)
{ {
MatrixParallelThread[] threadArr = _numaThreads[0]; MatrixParallelThread[] threadArr = numaWaveOrigin[0];
int retireCount = Math.Min(RESERVED_THREAD_COUNT, Math.Max(0, threadArr.Length)); int retireCount = Math.Min(RESERVED_THREAD_COUNT, Math.Max(0, threadArr.Length));
for (int i = 1; i <= retireCount; i++) { for (int i = 1; i <= retireCount; i++) {
RetireThread(threadArr[^i]); RetireThread(threadArr[^i]);
} }
_numaThreads[0] = threadArr[0..^retireCount]; _numaWaveFront[0] = [.. threadArr[0..^retireCount]];
} else } else
{ {
RetireWhenMultipleSIMDID(); RetireWhenMultipleSIMDID(numaWaveOrigin);
} }
_meaningful = _threads.Length > 1; _meaningful = _threads.Length > 1;
@@ -134,11 +134,13 @@ namespace StgSharp.Mathematics.Numeric
_retiredThreads.Push(thread); _retiredThreads.Push(thread);
} }
private static void RetireWhenMultipleSIMDID() private static void RetireWhenMultipleSIMDID(
MatrixParallelThread[][] threads
)
{ {
MatrixParallelThread[] allThreads = new MatrixParallelThread[Environment.ProcessorCount]; MatrixParallelThread[] allThreads = new MatrixParallelThread[Environment.ProcessorCount];
int offset = 0; int offset = 0;
foreach (MatrixParallelThread[] threadArr in _numaThreads) foreach (MatrixParallelThread[] threadArr in threads)
{ {
Array.Copy(threadArr, 0, allThreads, offset, threadArr.Length); Array.Copy(threadArr, 0, allThreads, offset, threadArr.Length);
offset += threadArr.Length; offset += threadArr.Length;
@@ -159,9 +161,9 @@ namespace StgSharp.Mathematics.Numeric
} }
// rebuild numa active arrays // rebuild numa active arrays
for (int numa = 0; numa < _numaThreads.Length; numa++) for (int numa = 0; numa < _numaWaveFront.Length; numa++)
{ {
MatrixParallelThread[] source = _numaThreads[numa]; MatrixParallelThread[] source = threads[numa];
int keepCount = 0; int keepCount = 0;
for (int i = 0; i < source.Length; i++) for (int i = 0; i < source.Length; i++)
@@ -181,7 +183,7 @@ namespace StgSharp.Mathematics.Numeric
} }
} }
_numaThreads[numa] = active; _numaWaveFront[numa] = [.. active];
} }
_threads = allThreads[retireCount..]; _threads = allThreads[retireCount..];
+27 -22
View File
@@ -17,18 +17,18 @@
#define GET_MK_PROC_STD(T_type, T_arch, T_feature, T_op) \ #define GET_MK_PROC_STD(T_type, T_arch, T_feature, T_op) \
((UNI_MK_PROC)MK_PROC_NAME_STD(T_type, T_arch, T_feature, T_op)) ((UNI_MK_PROC)MK_PROC_NAME_STD(T_type, T_arch, T_feature, T_op))
#define SN_MK_PROC_DECL(T_type, P_name) INTERNAL void SN_DECL P_name(MAT_TASK(T_type) const *task) #define SN_MK_PROC_DECL(T_type, P_name) INTERNAL void SN_DECL P_name(MAT_TASK(T_type) const *task)
#define SN_MK_PROC_DECL_STD(T_type, T_arch, T_feature, T_op) \ #define SN_MK_PROC_DECL_STD(T_type, T_arch, T_feature, T_op) \
INTERNAL NOINLINE SN_STD_TARGET_ATTR(T_arch, T_feature) void SN_DECL \ INTERNAL NOINLINE SN_STD_TARGET_ATTR(T_arch, T_feature) void SN_DECL MK_PROC_NAME_STD( \
MK_PROC_NAME_STD(T_type, T_arch, T_feature, T_op)(MAT_TASK(T_type) const *task) T_type, T_arch, T_feature, T_op)(MAT_TASK(T_type) const *task)
#define SK_PROC_NAME_STD(T_type, T_arch, T_feature, T_op) \ #define SK_PROC_NAME_STD(T_type, T_arch, T_feature, T_op) \
T_type##_single_kernel_proc_##T_op##_##T_arch##_##T_feature T_type##_single_kernel_proc_##T_op##_##T_arch##_##T_feature
#define GET_SK_PROC_STD(T_type, T_arch, T_feature, T_op) \ #define GET_SK_PROC_STD(T_type, T_arch, T_feature, T_op) \
((UNI_SK_PROC)SK_PROC_NAME_STD(T_type, T_arch, T_feature, T_op)) ((UNI_SK_PROC)SK_PROC_NAME_STD(T_type, T_arch, T_feature, T_op))
#define SN_SK_PROC_DECL_STD(T_type, T_arch, T_feature, T_op) \ #define SN_SK_PROC_DECL_STD(T_type, T_arch, T_feature, T_op) \
INTERNAL NOINLINE SN_STD_TARGET_ATTR(T_arch, T_feature) void SN_DECL \ INTERNAL NOINLINE SN_STD_TARGET_ATTR(T_arch, T_feature) void SN_DECL SK_PROC_NAME_STD( \
SK_PROC_NAME_STD(T_type, T_arch, T_feature, T_op)( \ T_type, T_arch, T_feature, \
MAT_KERNEL(T_type) const *left, MAT_KERNEL(T_type) const *right, \ T_op)(MAT_KERNEL(T_type) const *left, MAT_KERNEL(T_type) const *right, \
MAT_KERNEL(T_type) *restrict ans, uint64_t scalar) MAT_KERNEL(T_type) *restrict ans, uint64_t scalar)
#define _SN_STD__PROBE_0 0 #define _SN_STD__PROBE_0 0
#define _SN_STD__PROBE_1 1 #define _SN_STD__PROBE_1 1
@@ -43,27 +43,27 @@
#define _SN_MATPROC_RIGHT_ANS_SCALAR 1 #define _SN_MATPROC_RIGHT_ANS_SCALAR 1
#define _SN_MATPROC_ANS_SCALAR 1 #define _SN_MATPROC_ANS_SCALAR 1
#define _SN_MK_EXPAND_RIGHT_ANS \ #define _SN_MK_EXPAND_RIGHT_ANS \
SN_MAT_KERNEL_LOCAL const *right = (SN_MAT_KERNEL_LOCAL const *)task->mat_1; \ SN_MAT_KERNEL_LOCAL const *right = (SN_MAT_KERNEL_LOCAL const *)task->mat_1; \
SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->mat_2; SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->mat_2;
#define _SN_MK_EXPAND_LEFT_RIGHT_ANS \ #define _SN_MK_EXPAND_LEFT_RIGHT_ANS \
SN_MAT_KERNEL_LOCAL const *left = (SN_MAT_KERNEL_LOCAL const *)task->mat_0; \ SN_MAT_KERNEL_LOCAL const *left = (SN_MAT_KERNEL_LOCAL const *)task->mat_0; \
SN_MAT_KERNEL_LOCAL const *right = (SN_MAT_KERNEL_LOCAL const *)task->mat_1; \ SN_MAT_KERNEL_LOCAL const *right = (SN_MAT_KERNEL_LOCAL const *)task->mat_1; \
SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->mat_2; SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->mat_2;
#define _SN_MK_EXPAND_RIGHT_ANS_SCALAR \ #define _SN_MK_EXPAND_RIGHT_ANS_SCALAR \
SN_MAT_KERNEL_LOCAL const *right = (SN_MAT_KERNEL_LOCAL const *)task->mat_1; \ SN_MAT_KERNEL_LOCAL const *right = (SN_MAT_KERNEL_LOCAL const *)task->mat_1; \
SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->mat_2; \ SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->mat_2; \
scalar_pack *restrict scalar = (scalar_pack *restrict)task->scalar; scalar_pack *restrict scalar = (scalar_pack *restrict)task->scalar;
#define _SN_MK_EXPAND_LEFT_RIGHT_ANS_SCALAR \ #define _SN_MK_EXPAND_LEFT_RIGHT_ANS_SCALAR \
SN_MAT_KERNEL_LOCAL const *left = (SN_MAT_KERNEL_LOCAL const *)task->mat_0; \ SN_MAT_KERNEL_LOCAL const *left = (SN_MAT_KERNEL_LOCAL const *)task->mat_0; \
SN_MAT_KERNEL_LOCAL const *right = (SN_MAT_KERNEL_LOCAL const *)task->mat_1; \ SN_MAT_KERNEL_LOCAL const *right = (SN_MAT_KERNEL_LOCAL const *)task->mat_1; \
SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->mat_2; \ SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->mat_2; \
scalar_pack *restrict scalar = (scalar_pack *restrict)task->scalar; scalar_pack *restrict scalar = (scalar_pack *restrict)task->scalar;
#define _SN_MK_EXPAND_ANS_SCALAR \ #define _SN_MK_EXPAND_ANS_SCALAR \
SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->mat_2; \ SN_MAT_KERNEL_LOCAL *restrict ans = (SN_MAT_KERNEL_LOCAL *)task->mat_2; \
scalar_pack *restrict scalar = (scalar_pack *restrict)&(task->padding); scalar_pack *restrict scalar = (scalar_pack *restrict)&(task->padding);
@@ -74,9 +74,14 @@
#pragma region mem layout #pragma region mem layout
#define _SN_MATPROC_LAYOUT_BUFFER 1
#define _SN_MATPROC_LAYOUT_TILE 1 #define _SN_MATPROC_LAYOUT_TILE 1
#define _SN_MATPROC_LAYOUT_KERNEL 1 #define _SN_MATPROC_LAYOUT_KERNEL 1
#define _MK_MKPROC_EXPAND_INDEX_BUFFER \
size_t offset = UNSAFE_AS(size_t, task->padding.data[0]); \
size_t count = UNSAFE_AS(size_t, task->padding.data[1]);
#define _MK_MKPROC_EXPAND_INDEX_BUFFER \ #define _MK_MKPROC_EXPAND_INDEX_BUFFER \
size_t offset = UNSAFE_AS(size_t, task->padding.data[0]); \ size_t offset = UNSAFE_AS(size_t, task->padding.data[0]); \
size_t count = UNSAFE_AS(size_t, task->padding.data[1]); size_t count = UNSAFE_AS(size_t, task->padding.data[1]);
@@ -99,13 +104,13 @@
#pragma endregion #pragma endregion
#define __mk_param_std(mem, param, T) \ #define __mk_param_std(mem, param, T) \
typedef MAT_KERNEL(T) SN_MAT_KERNEL_LOCAL; \ typedef MAT_KERNEL(T) SN_MAT_KERNEL_LOCAL; \
matrix_task const *_ = (_SN_PARAM_STYLE(param), (_SN_MEM_LAYOUT(mem)), task); \ matrix_task const *_ = (_SN_PARAM_STYLE(param), (_SN_MEM_LAYOUT(mem)), task); \
_SN_MK_EXPAND_PARAM(param); \ _SN_MK_EXPAND_PARAM(param); \
_SN_MK_EXPAND_MEM(mem) _SN_MK_EXPAND_MEM(mem)
#define __sk_param_std(T) \ #define __sk_param_std(T) \
typedef MAT_KERNEL(T) SN_MAT_KERNEL_LOCAL; \ typedef MAT_KERNEL(T) SN_MAT_KERNEL_LOCAL; \
(void)scalar (void)scalar
#endif // !SN_INTRINSIC_PARAM_EXPAND #endif // !SN_INTRINSIC_PARAM_EXPAND
+38 -35
View File
@@ -1,37 +1,34 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/28.2.5 Chrome/138.0.7204.251 Electron/37.6.1 Safari/537.36" version="28.2.5"> <mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/28.2.5 Chrome/138.0.7204.251 Electron/37.6.1 Safari/537.36" version="28.2.5">
<diagram name="第 1 页" id="cbTJhW8NyRPDnIMFj9ZQ"> <diagram name="第 1 页" id="cbTJhW8NyRPDnIMFj9ZQ">
<mxGraphModel dx="2367" dy="1027" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#797979" math="0" shadow="0"> <mxGraphModel dx="1516" dy="401" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#797979" math="0" shadow="0">
<root> <root>
<mxCell id="0" /> <mxCell id="0" />
<mxCell id="1" parent="0" /> <mxCell id="1" parent="0" />
<mxCell id="25TvGm5YAioSoPTIv9tO-4" value="视图托管接口VH&lt;br&gt;ViewHost" style="rounded=0;whiteSpace=wrap;html=1;verticalAlign=bottom;gradientColor=none;fillColor=#3399FF;fontColor=#000000;strokeColor=none;" parent="1" vertex="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-4" value="视图托管接口VH&lt;br&gt;ViewHost" style="rounded=0;whiteSpace=wrap;html=1;verticalAlign=bottom;gradientColor=none;fillColor=#3399FF;fontColor=#000000;strokeColor=none;" parent="1" vertex="1">
<mxGeometry x="-210" y="40" width="430" height="200" as="geometry" /> <mxGeometry x="-116" y="40" width="250" height="200" as="geometry" />
</mxCell> </mxCell>
<mxCell id="oCZHK8Ia19RPNdtHcHY8-36" value="状态宿主 StateHost" style="verticalLabelPosition=middle;verticalAlign=top;html=1;shape=mxgraph.basic.rect;fillColor2=none;strokeWidth=1;size=0;indent=0;fillColor=#3399FF;labelPosition=center;align=center;strokeColor=none;" parent="1" vertex="1"> <mxCell id="oCZHK8Ia19RPNdtHcHY8-36" value="状态宿主 StateHost" style="verticalLabelPosition=middle;verticalAlign=top;html=1;shape=mxgraph.basic.rect;fillColor2=none;strokeWidth=1;size=0;indent=0;fillColor=#3399FF;labelPosition=center;align=center;strokeColor=none;" parent="1" vertex="1">
<mxGeometry x="-420" y="410" width="440" height="340" as="geometry" /> <mxGeometry x="-420" y="410" width="440" height="340" as="geometry" />
</mxCell> </mxCell>
<mxCell id="oCZHK8Ia19RPNdtHcHY8-37" value="呈现器VP&lt;br&gt;View Presenter" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="-200" y="50" width="210" height="70" as="geometry" />
</mxCell>
<mxCell id="oCZHK8Ia19RPNdtHcHY8-38" value="视图描述VD&lt;br&gt;View Descriptor" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1"> <mxCell id="oCZHK8Ia19RPNdtHcHY8-38" value="视图描述VD&lt;br&gt;View Descriptor" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="-200" y="120" width="210" height="70" as="geometry" /> <mxGeometry x="-106" y="50" width="110" height="140" as="geometry" />
</mxCell> </mxCell>
<mxCell id="oCZHK8Ia19RPNdtHcHY8-39" value="用户输入 I&lt;br&gt;Input" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1"> <mxCell id="oCZHK8Ia19RPNdtHcHY8-39" value="用户输入 I&lt;br&gt;Input" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="20" y="50" width="190" height="140" as="geometry" /> <mxGeometry x="15" y="50" width="99" height="140" as="geometry" />
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#66FF66;" parent="1" source="25TvGm5YAioSoPTIv9tO-4" target="25TvGm5YAioSoPTIv9tO-10" edge="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#66FF66;" parent="1" source="25TvGm5YAioSoPTIv9tO-4" target="25TvGm5YAioSoPTIv9tO-10" edge="1">
<mxGeometry relative="1" as="geometry"> <mxGeometry relative="1" as="geometry">
<Array as="points"> <Array as="points">
<mxPoint x="150" y="275" />
<mxPoint x="60" y="275" /> <mxPoint x="60" y="275" />
<mxPoint x="-7" y="275" />
</Array> </Array>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#66FF66;" parent="1" source="25TvGm5YAioSoPTIv9tO-4" target="25TvGm5YAioSoPTIv9tO-11" edge="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#66FF66;" parent="1" source="25TvGm5YAioSoPTIv9tO-4" target="25TvGm5YAioSoPTIv9tO-11" edge="1">
<mxGeometry relative="1" as="geometry"> <mxGeometry relative="1" as="geometry">
<Array as="points"> <Array as="points">
<mxPoint x="150" y="275" /> <mxPoint x="60" y="275" />
<mxPoint x="227" y="275" /> <mxPoint x="153" y="275" />
</Array> </Array>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
@@ -54,11 +51,12 @@
</Array> </Array>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeColor=#FFFF33;" parent="1" source="25TvGm5YAioSoPTIv9tO-7" target="25TvGm5YAioSoPTIv9tO-53" edge="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.336;entryY=1.014;entryDx=0;entryDy=0;strokeColor=#FFFF33;entryPerimeter=0;" parent="1" source="25TvGm5YAioSoPTIv9tO-7" target="25TvGm5YAioSoPTIv9tO-53" edge="1">
<mxGeometry relative="1" as="geometry"> <mxGeometry relative="1" as="geometry">
<Array as="points"> <Array as="points">
<mxPoint x="-310" y="390" /> <mxPoint x="-310" y="280" />
<mxPoint x="-310" y="390" /> <mxPoint x="-280" y="280" />
<mxPoint x="-280" y="240" />
</Array> </Array>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
@@ -69,7 +67,7 @@
<mxGeometry relative="1" as="geometry"> <mxGeometry relative="1" as="geometry">
<mxPoint x="-40" y="440" as="targetPoint" /> <mxPoint x="-40" y="440" as="targetPoint" />
<Array as="points"> <Array as="points">
<mxPoint x="60" y="390" /> <mxPoint x="-10" y="390" />
<mxPoint x="-40" y="390" /> <mxPoint x="-40" y="390" />
<mxPoint x="-40" y="440" /> <mxPoint x="-40" y="440" />
<mxPoint x="-39" y="440" /> <mxPoint x="-39" y="440" />
@@ -77,30 +75,30 @@
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-10" value="StateChangeCommand" style="rounded=1;whiteSpace=wrap;html=1;fontColor=#000000;strokeColor=none;fillColor=#66FF66;" parent="1" vertex="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-10" value="StateChangeCommand" style="rounded=1;whiteSpace=wrap;html=1;fontColor=#000000;strokeColor=none;fillColor=#66FF66;" parent="1" vertex="1">
<mxGeometry x="-13" y="310" width="146" height="20" as="geometry" /> <mxGeometry x="-80" y="335" width="146" height="20" as="geometry" />
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.945;entryY=0.011;entryDx=0;entryDy=0;strokeColor=#33FF33;entryPerimeter=0;" parent="1" source="25TvGm5YAioSoPTIv9tO-11" target="25TvGm5YAioSoPTIv9tO-7" edge="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.945;entryY=0.011;entryDx=0;entryDy=0;strokeColor=#33FF33;entryPerimeter=0;" parent="1" source="25TvGm5YAioSoPTIv9tO-11" target="25TvGm5YAioSoPTIv9tO-7" edge="1">
<mxGeometry relative="1" as="geometry"> <mxGeometry relative="1" as="geometry">
<Array as="points"> <Array as="points">
<mxPoint x="230" y="390" /> <mxPoint x="150" y="390" />
<mxPoint x="-40" y="390" /> <mxPoint x="-40" y="390" />
<mxPoint x="-40" y="440" />
</Array> </Array>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-11" value="CallOperationCommand" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=none;fillColor=#66FF66;fontColor=#000000;" parent="1" vertex="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-11" value="CallOperationCommand" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=none;fillColor=#66FF66;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="154" y="310" width="146" height="20" as="geometry" /> <mxGeometry x="80" y="335" width="146" height="20" as="geometry" />
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=1;entryDx=0;entryDy=0;strokeColor=#FFFF33;" parent="1" source="25TvGm5YAioSoPTIv9tO-16" target="25TvGm5YAioSoPTIv9tO-4" edge="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=1;entryDx=0;entryDy=0;strokeColor=#FFFF33;" parent="1" source="25TvGm5YAioSoPTIv9tO-16" target="25TvGm5YAioSoPTIv9tO-4" edge="1">
<mxGeometry relative="1" as="geometry"> <mxGeometry relative="1" as="geometry">
<Array as="points"> <Array as="points">
<mxPoint x="-107" y="275" /> <mxPoint x="-160" y="280" />
<mxPoint x="-102" y="275" /> <mxPoint x="-53" y="280" />
<mxPoint x="-53" y="240" />
</Array> </Array>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-16" value="CommandResult" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFFF33;fontColor=#000000;strokeColor=none;" parent="1" vertex="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-16" value="CommandResult" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFFF33;fontColor=#000000;strokeColor=none;" parent="1" vertex="1">
<mxGeometry x="-180" y="310" width="146" height="20" as="geometry" /> <mxGeometry x="-236" y="335" width="146" height="20" as="geometry" />
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-19" value="&lt;h1 style=&quot;margin-top: 0px;&quot;&gt;前端命令 FrontCommand&lt;/h1&gt;&lt;p&gt;&lt;span style=&quot;background-color: transparent;&quot;&gt;View和State通过前端命令进行交互&lt;br&gt;进程内通信可以直接传递对象&lt;br&gt;跨进程交互可以传递序列化后的json数据包&lt;br&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;State中响应command的结果通过CommandResult&lt;br&gt;数据包返回给View&lt;/p&gt;&lt;p&gt;在需要时,View通过前端命令获取State的快照进行图形化展示&lt;/p&gt;" style="text;html=1;whiteSpace=wrap;overflow=hidden;rounded=0;align=left;fontColor=#000000;" parent="1" vertex="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-19" value="&lt;h1 style=&quot;margin-top: 0px;&quot;&gt;前端命令 FrontCommand&lt;/h1&gt;&lt;p&gt;&lt;span style=&quot;background-color: transparent;&quot;&gt;View和State通过前端命令进行交互&lt;br&gt;进程内通信可以直接传递对象&lt;br&gt;跨进程交互可以传递序列化后的json数据包&lt;br&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;State中响应command的结果通过CommandResult&lt;br&gt;数据包返回给View&lt;/p&gt;&lt;p&gt;在需要时,View通过前端命令获取State的快照进行图形化展示&lt;/p&gt;" style="text;html=1;whiteSpace=wrap;overflow=hidden;rounded=0;align=left;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="-790" y="250" width="290" height="190" as="geometry" /> <mxGeometry x="-790" y="250" width="290" height="190" as="geometry" />
@@ -216,34 +214,36 @@
</Array> </Array>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-58" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=0;entryDx=0;entryDy=0;strokeColor=#66FF66;" parent="1" source="25TvGm5YAioSoPTIv9tO-53" target="25TvGm5YAioSoPTIv9tO-7" edge="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-58" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=0;entryDx=0;entryDy=0;strokeColor=#66FF66;exitX=0.511;exitY=0.992;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="25TvGm5YAioSoPTIv9tO-53" target="25TvGm5YAioSoPTIv9tO-7" edge="1">
<mxGeometry relative="1" as="geometry"> <mxGeometry relative="1" as="geometry">
<Array as="points"> <Array as="points">
<mxPoint x="-290" y="290" /> <mxPoint x="-260" y="240" />
<mxPoint x="-290" y="290" /> <mxPoint x="-260" y="300" />
<mxPoint x="-290" y="300" />
</Array> </Array>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-53" value="ViewHost 1" style="rounded=0;whiteSpace=wrap;html=1;verticalAlign=middle;gradientColor=none;fillColor=#3399FF;fontColor=#000000;strokeColor=none;" parent="1" vertex="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-53" value="ViewHost 1" style="rounded=0;whiteSpace=wrap;html=1;verticalAlign=middle;gradientColor=none;fillColor=#3399FF;fontColor=#000000;strokeColor=none;" parent="1" vertex="1">
<mxGeometry x="-400" y="210" width="180" height="30" as="geometry" /> <mxGeometry x="-340" y="210" width="180" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-54" value="ViewHost 2" style="rounded=0;whiteSpace=wrap;html=1;verticalAlign=middle;gradientColor=none;fillColor=#3399FF;fontColor=#000000;strokeColor=none;" parent="1" vertex="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-54" value="ViewHost 2" style="rounded=0;whiteSpace=wrap;html=1;verticalAlign=middle;gradientColor=none;fillColor=#3399FF;fontColor=#000000;strokeColor=none;" parent="1" vertex="1">
<mxGeometry x="-577" y="40" width="167" height="200" as="geometry" /> <mxGeometry x="-527" y="40" width="167" height="200" as="geometry" />
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#FFFF33;exitX=0;exitY=0;exitDx=0;exitDy=0;" parent="1" source="25TvGm5YAioSoPTIv9tO-7" edge="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#FFFF33;exitX=0;exitY=0;exitDx=0;exitDy=0;" parent="1" source="25TvGm5YAioSoPTIv9tO-7" edge="1">
<mxGeometry relative="1" as="geometry"> <mxGeometry relative="1" as="geometry">
<mxPoint x="-355.34000000000003" y="390" as="sourcePoint" /> <mxPoint x="-355.34000000000003" y="390" as="sourcePoint" />
<mxPoint x="-490" y="240" as="targetPoint" /> <mxPoint x="-450" y="240" as="targetPoint" />
<Array as="points"> <Array as="points">
<mxPoint x="-380" y="330" /> <mxPoint x="-380" y="330" />
<mxPoint x="-490" y="330" /> <mxPoint x="-450" y="330" />
<mxPoint x="-450" y="240" />
</Array> </Array>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-59" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.056;entryY=0.015;entryDx=0;entryDy=0;entryPerimeter=0;strokeColor=#66FF66;" parent="1" source="25TvGm5YAioSoPTIv9tO-54" target="25TvGm5YAioSoPTIv9tO-7" edge="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-59" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.056;entryY=0.015;entryDx=0;entryDy=0;entryPerimeter=0;strokeColor=#66FF66;" parent="1" source="25TvGm5YAioSoPTIv9tO-54" target="25TvGm5YAioSoPTIv9tO-7" edge="1">
<mxGeometry relative="1" as="geometry"> <mxGeometry relative="1" as="geometry">
<Array as="points"> <Array as="points">
<mxPoint x="-470" y="310" /> <mxPoint x="-410" y="310" />
<mxPoint x="-360" y="310" /> <mxPoint x="-360" y="310" />
</Array> </Array>
</mxGeometry> </mxGeometry>
@@ -298,13 +298,16 @@
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-78" value="" style="group" parent="1" vertex="1" connectable="0"> <mxCell id="25TvGm5YAioSoPTIv9tO-78" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="-420" y="870" width="120" height="180" as="geometry" /> <mxGeometry x="-420" y="870" width="210" height="180" as="geometry" />
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-79" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#0066CC;fontColor=#ffffff;strokeColor=#F5F5F5;" parent="25TvGm5YAioSoPTIv9tO-78" vertex="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-79" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#0066CC;fontColor=#ffffff;strokeColor=#F5F5F5;verticalAlign=top;" parent="25TvGm5YAioSoPTIv9tO-78" vertex="1">
<mxGeometry width="119.99999999999999" height="180" as="geometry" /> <mxGeometry width="119.99999999999999" height="180" as="geometry" />
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-80" value="服务 1&lt;br&gt;Service 1" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="25TvGm5YAioSoPTIv9tO-78" vertex="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-80" value="服务 1&lt;br&gt;Service 1" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="25TvGm5YAioSoPTIv9tO-78" vertex="1">
<mxGeometry y="75" width="119.99999999999999" height="30" as="geometry" /> <mxGeometry y="10" width="119.99999999999999" height="30" as="geometry" />
</mxCell>
<mxCell id="iwdWNZ0WjOj6HhX6wyoA-1" value="呈现器VP&lt;br&gt;View Presenter" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="25TvGm5YAioSoPTIv9tO-78">
<mxGeometry y="50" width="120" height="130" as="geometry" />
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-82" value="" style="group" parent="1" vertex="1" connectable="0"> <mxCell id="25TvGm5YAioSoPTIv9tO-82" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="-79" y="870" width="120" height="40" as="geometry" /> <mxGeometry x="-79" y="870" width="120" height="40" as="geometry" />
@@ -335,12 +338,12 @@
<mxGeometry x="-780" y="740" width="330" height="155" as="geometry" /> <mxGeometry x="-780" y="740" width="330" height="155" as="geometry" />
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-90" value="跨进程界面&lt;br&gt;ExternalDisplaySurface" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#FFFF99;fillColor=#FFFF99;fontColor=#000000;" parent="1" vertex="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-90" value="跨进程界面&lt;br&gt;ExternalDisplaySurface" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#FFFF99;fillColor=#FFFF99;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="-400" y="40" width="180" height="130" as="geometry" /> <mxGeometry x="-340" y="40" width="180" height="130" as="geometry" />
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-92" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endWidth=9.056603773584905;endSize=2.0638888888888887;startWidth=9.865229110512129;startSize=1.2074074074074073;width=2.7777777777777777;" parent="1" source="25TvGm5YAioSoPTIv9tO-53" target="25TvGm5YAioSoPTIv9tO-90" edge="1"> <mxCell id="25TvGm5YAioSoPTIv9tO-92" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endWidth=9.056603773584905;endSize=2.0638888888888887;startWidth=9.865229110512129;startSize=1.2074074074074073;width=2.7777777777777777;" parent="1" source="25TvGm5YAioSoPTIv9tO-53" target="25TvGm5YAioSoPTIv9tO-90" edge="1">
<mxGeometry width="100" height="100" relative="1" as="geometry"> <mxGeometry width="100" height="100" relative="1" as="geometry">
<mxPoint x="-360" y="290" as="sourcePoint" /> <mxPoint x="-300" y="290" as="sourcePoint" />
<mxPoint x="-260" y="190" as="targetPoint" /> <mxPoint x="-200" y="190" as="targetPoint" />
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="25TvGm5YAioSoPTIv9tO-93" value="json数据包" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=none;fontColor=#000000;" parent="25TvGm5YAioSoPTIv9tO-92" vertex="1" connectable="0"> <mxCell id="25TvGm5YAioSoPTIv9tO-93" value="json数据包" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=none;fontColor=#000000;" parent="25TvGm5YAioSoPTIv9tO-92" vertex="1" connectable="0">