在现代游戏开发中,多线程和异步编程技术是提升性能和用户体验的重要手段。Unity提供了一些工具和API来帮助开发者实现多线程和异步操作。以下是一些关键概念和技术,以及如何在Unity中使用它们。
1. Unity的主线程限制
首先需要了解的是,Unity的大部分API(尤其是与游戏对象和渲染相关的API)只能在主线程中调用。这是因为Unity的引擎架构设计使得大部分操作都依赖于主线程的更新循环。
2. Unity的协程(Coroutines)
协程是Unity中实现异步操作的主要方式之一。协程允许你在多个帧之间分割任务,而不会阻塞主线程。
using UnityEngine;
using System.Collections;
public class CoroutineExample : MonoBehaviour
{
void Start()
{
StartCoroutine(LoadData());
}
IEnumerator LoadData()
{
// 模拟一个耗时操作
yield return new WaitForSeconds(2.0f);
Debug.Log("Data Loaded");
}
}
3. C#的异步编程(Async/Await)
C#的async
和await
关键字提供了一种更现代和灵活的方式来处理异步操作。虽然Unity的API大部分不支持异步操作,但你可以使用Task
和async/await
来处理非Unity API的异步任务。
using UnityEngine;
using System.Threading.Tasks;
public class AsyncAwaitExample : MonoBehaviour
{
async void Start()
{
await LoadDataAsync();
Debug.Log("Data Loaded");
}
async Task LoadDataAsync()
{
// 模拟一个耗时操作
await Task.Delay(2000);
}
}
4. Unity的Job System
Unity的Job System允许你在多线程环境中执行高性能的并行计算。Job System与Burst编译器结合使用,可以显著提高性能。
4.1 创建一个简单的Job
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
public class JobSystemExample : MonoBehaviour
{
void Start()
{
NativeArray<int> data = new NativeArray<int>(100, Allocator.TempJob);
MyJob job = new MyJob { data = data };
JobHandle handle = job.Schedule();
handle.Complete();
// 使用数据
Debug.Log(data[0]);
data.Dispose();
}
struct MyJob : IJob
{
public NativeArray<int> data;
public void Execute()
{
for (int i = 0; i < data.Length; i++)
{
data[i] = i * 2;
}
}
}
}
4.2 使用Burst编译器
Burst编译器可以显著优化Job的性能。要使用Burst编译器,需要在Job结构体上添加[BurstCompile]
属性。
using Unity.Burst;
using Unity.Jobs;
using Unity.Collections;
public class BurstJobExample : MonoBehaviour
{
void Start()
{
NativeArray<int> data = new NativeArray<int>(100, Allocator.TempJob);
MyBurstJob job = new MyBurstJob { data = data };
JobHandle handle = job.Schedule();
handle.Complete();
// 使用数据
Debug.Log(data[0]);
data.Dispose();
}
[BurstCompile]
struct MyBurstJob : IJob
{
public NativeArray<int> data;
public void Execute()
{
for (int i = 0; i < data.Length; i++)
{
data[i] = i * 2;
}
}
}
}
5. Unity的Task和Thread
虽然Unity不推荐直接使用C#的Thread
类进行多线程编程,但在某些情况下,使用Task
和Thread
可以提供更大的灵活性。
5.1 使用Task
using UnityEngine;
using System.Threading.Tasks;
public class TaskExample : MonoBehaviour
{
void Start()
{
Task.Run(() => DoWork());
}
void DoWork()
{
// 模拟一个耗时操作
System.Threading.Thread.Sleep(2000);
Debug.Log("Work Done");
}
}
5.2
继续使用Thread的示例:
using UnityEngine;
using System.Threading;
public class ThreadExample : MonoBehaviour
{
void Start()
{
Thread thread = new Thread(DoWork);
thread.Start();
}
void DoWork()
{
// 模拟一个耗时操作
Thread.Sleep(2000);
Debug.Log("Work Done");
}
}
6. Unity的Task和Thread的注意事项
虽然使用Task
和Thread
可以提供更大的灵活性,但需要注意以下几点:
- 线程安全:确保在多线程环境中访问共享资源时,使用适当的同步机制(如锁、互斥量等)来避免数据竞争和死锁。
- 主线程限制:Unity的大部分API只能在主线程中调用,因此需要在主线程中执行与Unity API相关的操作。可以使用
UnityMainThreadDispatcher
或类似的工具来在主线程中执行操作。 - 性能开销:创建和管理线程有一定的性能开销,因此在使用多线程时需要权衡性能和复杂性。
7. Unity的异步资源加载
Unity提供了一些异步API来加载资源,如Resources.LoadAsync
和AssetBundle.LoadAssetAsync
。这些API可以在不阻塞主线程的情况下加载资源。
7.1 使用Resources.LoadAsync
using UnityEngine;
using System.Collections;
public class AsyncResourceLoader : MonoBehaviour
{
void Start()
{
StartCoroutine(LoadResourceAsync("MyPrefab"));
}
IEnumerator LoadResourceAsync(string resourcePath)
{
ResourceRequest request = Resources.LoadAsync<GameObject>(resourcePath);
yield return request;
if (request.asset != null)
{
GameObject prefab = request.asset as GameObject;
Instantiate(prefab);
}
}
}
7.2 使用Addressables
Addressables是Unity提供的一个更现代的资源管理系统,支持异步加载和资源管理。
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class AddressablesExample : MonoBehaviour
{
void Start()
{
LoadAddressableAsset("MyPrefab");
}
void LoadAddressableAsset(string address)
{
Addressables.LoadAssetAsync<GameObject>(address).Completed += OnAssetLoaded;
}
void OnAssetLoaded(AsyncOperationHandle<GameObject> handle)
{
if (handle.Status == AsyncOperationStatus.Succeeded)
{
GameObject prefab = handle.Result;
Instantiate(prefab);
}
}
}
8. 结论
多线程和异步编程技术在Unity中可以显著提升性能和用户体验。通过合理使用协程、C#的async/await
、Unity的Job System、Burst编译器以及异步资源加载API,可以有效地管理复杂的任务和资源加载。
在实际项目中,选择合适的技术和工具,并注意线程安全和主线程限制,是成功实现多线程和异步编程的关键。希望这些信息和示例能帮助你更好地理解和使用Unity的多线程和异步编程技术。如果你有更多问题或需要进一步的帮助,请随时提问!
当然,接下来我们可以深入探讨一些更高级的多线程和异步编程技术,以及在Unity中使用这些技术时的一些最佳实践和注意事项。
9. 高级多线程和异步编程技术
9.1 Unity的Job System和Burst编译器的高级用法
Unity的Job System和Burst编译器是非常强大的工具,适用于需要高性能计算的场景。以下是一些高级用法和优化技巧。
9.1.1 并行For循环
IJobParallelFor
接口允许你在多个线程上并行执行循环体,从而显著提高性能。
using Unity.Burst;
using Unity.Jobs;
using Unity.Collections;
public class ParallelForJobExample : MonoBehaviour
{
void Start()
{
NativeArray<int> data = new NativeArray<int>(100, Allocator.TempJob);
MyParallelForJob job = new MyParallelForJob { data = data };
JobHandle handle = job.Schedule(data.Length, 10);
handle.Complete();
// 使用数据
Debug.Log(data[0]);
data.Dispose();
}
[BurstCompile]
struct MyParallelForJob : IJobParallelFor
{
public NativeArray<int> data;
public void Execute(int index)
{
data[index] = index * 2;
}
}
}
9.1.2 Job Dependencies
在复杂的多线程环境中,任务之间可能存在依赖关系。Unity的Job System允许你定义任务依赖,以确保任务按正确的顺序执行。
using Unity.Burst;
using Unity.Jobs;
using Unity.Collections;
public class JobDependenciesExample : MonoBehaviour
{
void Start()
{
NativeArray<int> data = new NativeArray<int>(100, Allocator.TempJob);
MyJob job1 = new MyJob { data = data };
JobHandle handle1 = job1.Schedule();
MyJob job2 = new MyJob { data = data };
JobHandle handle2 = job2.Schedule(handle1);
handle2.Complete();
// 使用数据
Debug.Log(data[0]);
data.Dispose();
}
[BurstCompile]
struct MyJob : IJob
{
public NativeArray<int> data;
public void Execute()
{
for (int i = 0; i < data.Length; i++)
{
data[i] = i * 2;
}
}
}
}
9.2 Unity的Task和Thread的高级用法
9.2.1 使用CancellationToken取消任务
在某些情况下,你可能需要取消正在进行的任务。CancellationToken
可以帮助你实现这一功能。
using UnityEngine;
using System.Threading;
using System.Threading.Tasks;
public class CancellationTokenExample : MonoBehaviour
{
private CancellationTokenSource cts;
void Start()
{
cts = new CancellationTokenSource();
Task.Run(() => DoWork(cts.Token));
}
void OnDestroy()
{
cts.Cancel();
}
async Task DoWork(CancellationToken token)
{
for (int i = 0; i < 10; i++)
{
if (token.IsCancellationRequested)
{
Debug.Log("Task Cancelled");
return;
}
// 模拟一个耗时操作
await Task.Delay(1000);
Debug.Log("Work Done");
}
}
}
9.2.2 使用Concurrent Collections
在多线程环境中,使用线程安全的集合可以避免数据竞争和死锁。System.Collections.Concurrent
命名空间提供了一些线程安全的集合类。
using UnityEngine;
using System.Collections.Concurrent;
using System.Threading.Tasks;
public class ConcurrentCollectionsExample : MonoBehaviour
{
private ConcurrentQueue<int> queue = new ConcurrentQueue<int>();
void Start()
{
Task.Run(() => Producer());
Task.Run(() => Consumer());
}
void Producer()
{
for (int i = 0; i < 10; i++)
{
queue.Enqueue(i);
Debug.Log("Produced: " + i);
System.Threading.Thread.Sleep(500);
}
}
void Consumer()
{
while (true)
{
if (queue.TryDequeue(out int result))
{
Debug.Log("Consumed: " + result);
}
System.Threading.Thread.Sleep(100);
}
}
}
10. 最佳实践和注意事项(续)
10.1 避免主线程阻塞
确保在主线程中执行的操作尽量简短,以避免阻塞主线程,导致帧率下降和用户体验不佳。以下是一些避免主线程阻塞的策略:
- 异步加载资源:使用异步API(如
Resources.LoadAsync
或Addressables
)加载资源。 - 分帧处理:将复杂的计算任务分割成多个帧处理,使用协程或Job System来实现。
- 后台线程:将耗时的计算任务放到后台线程中执行,使用
Task
或Thread
。
10.2 线程安全
在多线程环境中,确保对共享资源的访问是线程安全的。以下是一些常见的线程安全技术:
- 锁(Lock):使用
lock
关键字保护共享资源。 - 互斥量(Mutex):使用
Mutex
类实现线程间的互斥。 - 线程安全集合:使用
System.Collections.Concurrent
命名空间中的线程安全集合类,如ConcurrentQueue
、ConcurrentDictionary
等。
10.3 主线程回调
在后台线程中完成任务后,通常需要在主线程中更新UI或游戏对象。可以使用UnityMainThreadDispatcher
或类似的工具来实现主线程回调。
using UnityEngine;
using System.Threading.Tasks;
public class MainThreadCallbackExample : MonoBehaviour
{
void Start()
{
Task.Run(() => DoWork());
}
async Task DoWork()
{
// 模拟一个耗时操作
await Task.Delay(2000);
// 在主线程中执行回调
UnityMainThreadDispatcher.Instance().Enqueue(() => {
Debug.Log("Work Done on Main Thread");
});
}
}
10.4 使用Profiler进行性能分析
Unity的Profiler工具可以帮助你分析和优化多线程和异步操作的性能。通过Profiler,你可以查看每一帧的CPU和GPU使用情况,找出性能瓶颈。
10.5 避免过度使用多线程
虽然多线程和异步编程可以显著提高性能,但过度使用可能导致代码复杂性增加和难以调试。应根据实际需求合理使用多线程技术。
11. 实际案例
以下是一个综合使用多线程和异步编程技术的实际案例,展示如何在Unity中实现高效的资源加载和处理。
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using System.Threading.Tasks;
using System.Collections.Concurrent;
public class AdvancedExample : MonoBehaviour
{
private ConcurrentQueue<GameObject> loadedPrefabs = new ConcurrentQueue<GameObject>();
void Start()
{
LoadAndProcessAssets();
}
async void LoadAndProcessAssets()
{
// 异步加载资源
var handle = Addressables.LoadAssetAsync<GameObject>("MyPrefab");
await handle.Task;
if (handle.Status == AsyncOperationStatus.Succeeded)
{
GameObject prefab = handle.Result;
loadedPrefabs.Enqueue(prefab);
// 在后台线程中处理资源
Task.Run(() => ProcessAssets());
}
}
void ProcessAssets()
{
while (loadedPrefabs.TryDequeue(out GameObject prefab))
{
// 模拟耗时处理
System.Threading.Thread.Sleep(1000);
// 在主线程中实例化对象
UnityMainThreadDispatcher.Instance().Enqueue(() => {
Instantiate(prefab);
Debug.Log("Prefab Instantiated on Main Thread");
});
}
}
}
12. 结论
多线程和异步编程技术在Unity中是提升性能和用户体验的重要手段。通过合理使用协程、C#的async/await
、Unity的Job System、Burst编译器以及异步资源加载API,可以有效地管理复杂的任务和资源加载。
在实际项目中,选择合适的技术和工具,并注意线程安全和主线程限制,是成功实现多线程和异步编程的关键。希望这些信息和示例能帮助你更好地理解和使用Unity的多线程和异步编程技术。如果你有更多问题或需要进一步的帮助,请随时提问!
当然,我们可以继续深入探讨一些更高级的主题和技术,进一步提升你在Unity中使用多线程和异步编程的能力。
13. 高级主题
13.1 Unity的ECS(实体组件系统)
Unity的ECS(Entity Component System)是一个高性能的数据驱动编程模型,特别适合处理大量实体的场景。ECS与Job System和Burst编译器紧密集成,可以显著提高性能。
13.1.1 基本概念
- Entity(实体):一个轻量级的ID,用于标识游戏对象。
- Component(组件):数据容器,存储实体的属性。
- System(系统):逻辑处理单元,操作组件数据。
13.1.2 示例
以下是一个简单的ECS示例,展示如何创建实体、组件和系统。
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
using UnityEngine;
public class ECSSample : MonoBehaviour
{
private EntityManager entityManager;
void Start()
{
entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
// 创建一个实体原型
EntityArchetype archetype = entityManager.CreateArchetype(
typeof(Translation),
typeof(Rotation),
typeof(RenderMesh),
typeof(LocalToWorld)
);
// 创建实体
Entity entity = entityManager.CreateEntity(archetype);
// 设置组件数据
entityManager.SetComponentData(entity, new Translation { Value = new float3(0, 0, 0) });
entityManager.SetComponentData(entity, new Rotation { Value = quaternion.identity });
// 添加渲染组件
entityManager.AddSharedComponentData(entity, new RenderMesh
{
mesh = Resources.GetBuiltinResource<Mesh>("Cube.fbx"),
material = Resources.GetBuiltinResource<Material>("Default-Material.mat")
});
}
}
13.1.3 系统
系统是ECS的核心部分,负责处理组件数据。以下是一个简单的系统示例,展示如何更新实体的位置。
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
public class MoveSystem : SystemBase
{
protected override void OnUpdate()
{
float deltaTime = Time.DeltaTime;
Entities.ForEach((ref Translation translation) =>
{
translation.Value.y += 1f * deltaTime;
}).ScheduleParallel();
}
}
13.2 Unity的DOTS(Data-Oriented Technology Stack)
Unity的DOTS(Data-Oriented Technology Stack)是一个高性能的编程框架,包含ECS、Job System和Burst编译器。DOTS旨在充分利用现代多核处理器的性能。
13.2.1 DOTS的优势
- 高性能:通过数据驱动的设计和多线程并行处理,显著提高性能。
- 可扩展性:适用于处理大量实体和复杂逻辑的场景。
- 易于维护:数据和逻辑分离,代码更易于维护和扩展。
13.2.2 DOTS示例
以下是一个使用DOTS的示例,展示如何创建和更新大量实体。
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
using UnityEngine;
public class DOTSSample : MonoBehaviour
{
private EntityManager entityManager;
void Start()
{
entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
// 创建一个实体原型
EntityArchetype archetype = entityManager.CreateArchetype(
typeof(Translation),
typeof(Rotation),
typeof(RenderMesh),
typeof(LocalToWorld)
);
// 创建大量实体
for (int i = 0; i < 1000; i++)
{
Entity entity = entityManager.CreateEntity(archetype);
entityManager.SetComponentData(entity, new Translation { Value = new float3(i * 1.5f, 0, 0) });
entityManager.SetComponentData(entity, new Rotation { Value = quaternion.identity });
entityManager.AddSharedComponentData(entity, new RenderMesh
{
mesh = Resources.GetBuiltinResource<Mesh>("Cube.fbx"),
material = Resources.GetBuiltinResource<Material>("Default-Material.mat")
});
}
}
}
14. 进一步学习资源(续)
为了更深入地理解和掌握Unity的多线程和异步编程技术,以下是一些推荐的学习资源:
14.1 官方文档和教程
-
Unity官方文档:Unity的官方文档是了解Unity各项功能和API的最佳资源。特别是关于Job System、Burst编译器和ECS的部分。
-
Unity Learn:Unity提供了大量的免费和付费教程,涵盖了从基础到高级的各种主题。
14.2 社区和论坛
-
Unity论坛:Unity的官方论坛是一个活跃的社区,开发者可以在这里提问、分享经验和获取帮助。
-
Stack Overflow:这是一个广泛使用的问答平台,许多Unity开发者在这里分享他们的经验和解决方案。
14.3 博客和视频教程
-
Unity官方博客:Unity的官方博客经常发布关于新功能、最佳实践和案例研究的文章。
-
YouTube频道:许多开发者和教育者在YouTube上发布了大量的Unity教程视频,涵盖了从基础到高级的各种主题。
14.4 书籍
-
《Unity in Action》:这本书涵盖了Unity开发的各个方面,包括多线程和异步编程。
- 作者:Joe Hocking
-
《C# 7.0 in a Nutshell》:这本书详细介绍了C#语言的各个方面,包括异步编程和多线程。
- 作者:Joseph Albahari, Ben Albahari
15. 实践项目
为了更好地掌握多线程和异步编程技术,建议你通过实际项目进行练习。以下是一些可以尝试的项目:
15.1 异步资源加载器
创建一个异步资源加载器,能够在后台加载资源并在主线程中实例化对象。这个项目可以帮助你熟悉异步编程和主线程回调。
15.2 多线程路径寻路
实现一个多线程的A*路径寻路算法,用于处理大量单位的路径计算。这个项目可以帮助你理解多线程编程和数据同步。
15.3 ECS游戏
使用Unity的ECS框架创建一个简单的游戏,例如一个小型的塔防游戏或射击游戏。这个项目可以帮助你熟悉ECS的基本概念和使用方法。
16. 结论
多线程和异步编程技术在Unity中是提升性能和用户体验的重要手段。通过合理使用协程、C#的async/await
、Unity的Job System、Burst编译器以及ECS和DOTS,可以有效地管理复杂的任务和资源加载。
在实际项目中,选择合适的技术和工具,并注意线程安全和主线程限制,是成功实现多线程和异步编程的关键。希望这些信息和示例能帮助你更好地理解和使用Unity的多线程和异步编程技术。如果你有更多问题或需要进一步的帮助,请随时提问!
祝你在Unity开发中取得成功!
当然,我们可以继续深入探讨一些更高级的主题和技术,进一步提升你在Unity中使用多线程和异步编程的能力。
17. 高级优化技术
17.1 内存管理
在多线程和异步编程中,内存管理是一个重要的考虑因素。以下是一些优化内存使用的技术:
17.1.1 对象池
对象池是一种优化技术,通过重用对象来减少内存分配和垃圾回收的开销。以下是一个简单的对象池示例:
using System.Collections.Generic;
using UnityEngine;
public class ObjectPool : MonoBehaviour
{
public GameObject prefab;
private Queue<GameObject> pool = new Queue<GameObject>();
public GameObject GetObject()
{
if (pool.Count > 0)
{
GameObject obj = pool.Dequeue();
obj.SetActive(true);
return obj;
}
else
{
return Instantiate(prefab);
}
}
public void ReturnObject(GameObject obj)
{
obj.SetActive(false);
pool.Enqueue(obj);
}
}
17.1.2 内存对齐
在使用Unity的Burst编译器时,内存对齐可以显著提高性能。Burst编译器会自动优化内存对齐,但你也可以手动进行优化。例如,使用NativeArray
和NativeSlice
来确保数据在内存中的连续性和对齐。
using Unity.Collections;
using Unity.Jobs;
using Unity.Burst;
using UnityEngine;
public class MemoryAlignmentExample : MonoBehaviour
{
[BurstCompile]
struct MyJob : IJob
{
public NativeArray<float> data;
public void Execute()
{
for (int i = 0; i < data.Length; i++)
{
data[i] *= 2;
}
}
}
void Start()
{
NativeArray<float> data = new NativeArray<float>(100, Allocator.TempJob);
MyJob job = new MyJob { data = data };
JobHandle handle = job.Schedule();
handle.Complete();
data.Dispose();
}
}
17.2 数据局部性
数据局部性是指在内存中存储的数据尽可能接近,以提高缓存命中率和访问速度。在ECS中,数据局部性是通过将相关组件存储在连续的内存块中实现的。
17.2.1 示例
以下是一个ECS示例,展示如何利用数据局部性优化性能:
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
using UnityEngine;
public class DataLocalityExample : MonoBehaviour
{
private EntityManager entityManager;
void Start()
{
entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
// 创建一个实体原型
EntityArchetype archetype = entityManager.CreateArchetype(
typeof(Translation),
typeof(Rotation)
);
// 创建大量实体
for (int i = 0; i < 1000; i++)
{
Entity entity = entityManager.CreateEntity(archetype);
entityManager.SetComponentData(entity, new Translation { Value = new float3(i * 1.5f, 0, 0) });
entityManager.SetComponentData(entity, new Rotation { Value = quaternion.identity });
}
}
}
17.3 并行化算法
在多线程编程中,并行化算法是提高性能的关键。以下是一些常见的并行化算法和技术:
17.3.1 并行循环
使用C#的Parallel.For
或Unity的Job System可以轻松实现并行循环。例如,以下是一个使用Parallel.For
的示例:
using System.Threading.Tasks;
using UnityEngine;
public class ParallelForExample : MonoBehaviour
{
void Start()
{
int[] data = new int[1000];
Parallel.For(0, data.Length, i =>
{
data[i] = i * i;
});
foreach (var item in data)
{
Debug.Log(item);
}
}
}
好的,我们继续深入探讨并行化算法和其他高级优化技术。
17.3 并行化算法(续)
17.3.2 并行排序(续)
并行排序是一种将排序任务分割成多个子任务并行执行的技术。以下是一个使用Parallel.For
实现并行快速排序的示例:
using System;
using System.Threading.Tasks;
public class ParallelQuickSort
{
public static void QuickSort(int[] array, int left, int right)
{
if (left < right)
{
int pivot = Partition(array, left, right);
// 使用Parallel.Invoke并行执行两个子任务
Parallel.Invoke(
() => QuickSort(array, left, pivot - 1),
() => QuickSort(array, pivot + 1, right)
);
}
}
private static int Partition(int[] array, int left, int right)
{
int pivot = array[right];
int i = left - 1;
for (int j = left; j < right; j++)
{
if (array[j] <= pivot)
{
i++;
Swap(array, i, j);
}
}
Swap(array, i + 1, right);
return i + 1;
}
private static void Swap(int[] array, int i, int j)
{
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
你可以在Unity项目中使用这个并行快速排序算法来处理需要高效排序的大量数据。
17.3.3 并行矩阵乘法
矩阵乘法是许多科学计算和图形处理中的基础操作。以下是一个使用Parallel.For
实现并行矩阵乘法的示例:
using System;
using System.Threading.Tasks;
public class ParallelMatrixMultiplication
{
public static float[,] Multiply(float[,] matrixA, float[,] matrixB)
{
int rowsA = matrixA.GetLength(0);
int colsA = matrixA.GetLength(1);
int rowsB = matrixB.GetLength(0);
int colsB = matrixB.GetLength(1);
if (colsA != rowsB)
throw new InvalidOperationException("Matrix dimensions are not compatible for multiplication.");
float[,] result = new float[rowsA, colsB];
Parallel.For(0, rowsA, i =>
{
for (int j = 0; j < colsB; j++)
{
float sum = 0;
for (int k = 0; k < colsA; k++)
{
sum += matrixA[i, k] * matrixB[k, j];
}
result[i, j] = sum;
}
});
return result;
}
}