Unity Engine

[Unity]Job System + String

Aostols 2023. 3. 3. 22:36
반응형

Unity Job System에서는 NativeArray를 사용하기 떄문에 기본적으로 string으로 사용하지 못합니다.

정확히는 NativeArray<string>을 사용하지 못합니다.

금칙어를 구현하는 과정이었고 다량의 string비교가 있어서 성능적인 이슈가 많아 Job을 사용하려고 Job + string을 여러 방면으로 연구 하였고 방법을 찾긴 했지만 효과적이지 못했습니다.

부분적으로나마 JobSystem + string을 사용 가능한 방법을 찾아 정리해 봅니다.

 

private NativeArray<byte> _sourceWords;
private NativeArray<byte> _result;

private string _testString = "hello\nworld\nhealthy\ncoffee\ncafe\nkeyboard";

일단 테스트할 string이 있고 Job처리를 위한 NativeArray2개를 만들어 줍니다.

NativeArray는 byte형태로 결국 string => byte[]형태가 됩니다.

 

void Start()
{
    byte[] byteString = System.Text.Encoding.Default.GetBytes(_testString);

    _sourceWords = new NativeArray<byte>(byteString, Allocator.TempJob);
    _result = new NativeArray<byte>(_testString.Length, Allocator.TempJob);

    WordChangeJob job = new WordChangeJob();
    job.SourceWords = _sourceWords;
    job.Result = _result;
    JobHandle handle = job.Schedule(_result.Length, 1);
    handle.Complete();

    string resultString = System.Text.Encoding.UTF8.GetString(_result.ToArray());
    Debug.Log(resultString);

    _sourceWords.Dispose();
    _result.Dispose();
}

이제 _testString을 byte[]로 인코딩해서 저장해 줍니다.

나머지는 기본적인 Job처리로 결과를 얻어오고 얻어온 byte[]를 다시 string으로 변환 해 줍니다.

 

public struct WordChangeJob : IJobParallelFor
{
    public NativeArray<byte> SourceWords;
    public NativeArray<byte> Result;
    public void Execute(int index)
    {
        string testString = System.Text.Encoding.UTF8.GetString(SourceWords.ToArray());

        if (testString[index] == 'o')
        {
            testString = $"{testString.Substring(0, index)}0{testString.Substring(index + 1)}";
        }
        byte[] _result = System.Text.Encoding.Default.GetBytes(testString);
        Result[index] = _result[index];
    }
}

Job 구현부분이 중요한 부분인데 IJobParallelFor를 사용 했습니다.

SourceWords 는 외부에서 입력하였으니 실행부에서는 string으로 변환 합니다.

이제 여기서 알파벳'o'를 숫자 '0'으로 변환하는 식 입니다.

그리고 그 결과를 다시 byte[]로 변환하여 Result에 넣어 줍니다.

 

전반적인 동작은 원활히 이루어 지고 있습니다.

string을 byte[]로 넘겨받아 처리하고 있으며, char의 변환도 잘 이루어 지고 있습니다.

 

다만 사용하지 못한 이유가 몇가지 있습니다.

1. 너무 큰 string

2. 1번과 연관되어 Job에서 쪼개기 애매한 string

3. 다국어 처리의 모호함.

4. 성능에 대한 의문

 

1번의 경우 금칙어 단어가 8천개에서 만개가량 있습니다.

이 모든 단어를 byte[]로 만들어서 넣기에 양이 너무 많다고 판단 하였습니다.

2번의 경우 1번과 연관되는 것으로 이상적인 내용은 1단어를 1개의 Job에서 비교하여 처리하는 것인데 그렇다면 서로 다른 Job객체를 8천개 만들어야 하는데 약간의 의문점이 들었습니다.

3번은 byte[]로 변환하는 과정에서의 문제로 다국어가 들어가게 되면 인코딩을 어떻게 할지, 2바이트로 넘어가게 되면 IJobParallelFor를 사용하지 못할것으로 보였습니다.

또한 이 모든것을 감수하고도 한다면 string -> byte[]전환의 오버헤드를 감수하고도 성능이 제대로 나올지도 약간의 의문이 들었습니다.

 

전반적으로 확신이 들지 못하여 끝까지 진행하지 못하였지만 그래도 string을 일부나마 Job에서 사용할수 있음을 알 수 있는 계기가 되었습니다.

 

반응형

'Unity Engine' 카테고리의 다른 글

[Unity] Animation Controller  (0) 2023.04.23
[Unity] ScriptableObject + Reflection  (0) 2023.03.28
Cinemachine - Impulse + SecondaryNoise  (0) 2023.02.09
Cinemachine - Impulse  (0) 2023.01.02
Cinemachine - Noise  (0) 2022.12.29