मैंने हाल ही में मंच पर एक प्रश्न पूछा कि वायदा प्राप्त करने के बाद निष्पादक सेवा मेरे कार्यक्रम को क्यों रोक रही थी: ExecutorService और Future मुख्य थ्रेड को ब्लॉक कर रहे हैं

बात यह है कि बहुत सारी डिबगिंग के बाद, दोषी लाइन फ्यूचर नहीं थी। () लेकिन int vaoID = GL30.glGenVertexArrays();

मैं संक्षेप में बताऊंगा कि मैं क्या करने की कोशिश कर रहा हूं, और फिर कोड पोस्ट करूंगा। मूल रूप से, जैसे ही खिलाड़ी चलता है, मैं इलाके पैदा कर रहा हूं। जब भी पीढ़ी होती है तो गेम को फ्रीज करने से बचने के लिए, मैंने कॉलबल्स और एक्ज़ीक्यूटर सर्विस और फ्यूचर्स के साथ मल्टीथ्रेडिंग लागू की। इसलिए जब मुझे इलाके उत्पन्न करने होते हैं तो मैं निष्पादक सेवा में नए कार्य सबमिट कर रहा हूं (कार्य इलाके के सभी शिखर/मानदंड/रंगों की गणना करना है), और फिर प्रत्येक भविष्य के लिए, यदि यह किया जाता है तो मुझे परिणाम मिल रहा है और इलाके का मॉडल तैयार करते हैं। लेकिन प्रत्येक फ्रेम में, पहला भविष्य जो समाप्त होता है, एक फ्रीज का कारण बनता है। वास्तव में, यह भविष्य ही नहीं है जो इसे पैदा कर रहा है बल्कि मॉडल का निर्माण, और अधिक सटीक रूप से int vaoID = GL30.glGenVertexArrays(); विधि है।

संक्षेप में, मुझे लगता है कि glGenVertexArrays (); धागे को अवरुद्ध कर रहा है, शायद अन्य धागे खत्म होने की प्रतीक्षा कर रहा है, और मेरे पास क्या हो रहा है इसका एक भी सुराग नहीं है। मैं एलडब्ल्यूजेजीएल 2 और ओपनजीएल 3.0+ का उपयोग कर रहा हूं।

यहां वह कोड है जो मल्टीथ्रेडिंग को संभालता है:


//method called each frame
private void checkForFutures(List<Future<SomeClass>> terrainsInCreation) {
        try
        {
            List<Future<SomeClass>> futuresToRemove = new ArrayList<Future<SomeClass>>();
            for(Future<SomeClass> future:terrainsInCreation) {
                if(future.isDone()) {
                    float time = DisplayManager.getCurrentTime();
                    try {
                        SomeClass t = future.get();
                        Key key = new Key(t.terrain.getChunkX(),t.terrain.getChunkZ());
                        t.terrain.generateTerrain(loader, t.vertices, t.indices,t.colors, t.normals); // Guilty line !
                        futuresToRemove.add(future);
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                        Thread.sleep(1000000);
                    }
                }
            }
            terrainsInCreation.removeAll(futuresToRemove);
        }
        catch (InterruptedException ie)
        {
            System.err.println("BIG PROBLEM ON TERRAIN MANAGER");          
        }
    }

//method called when I have terrains to generate
    private void generate(List<Callable<SomeClass>> terrainsToCreate) {

        for(int i = 0; i < terrainsToCreate.size();i++) {
            terrainsInCreation.add(executor.submit(terrainsToCreate.get(i)));
        } 
    }

जेनरेट टेरेन () विधि यहां दी गई है:

        int vaoID = createVAO();
        bindIndicesBuffer(indices);
        storeDataInAttributeList(0,3, positions);
        storeDataInAttributeList(1,3, colors);
        storeDataInAttributeList(2, 3, normals);

        unbindVAO();
        
        return new RawModel(vaoID, indices.length);


(मैंने कोड को सरल बनाया)

और यहां createVao() विधि है:


private int createVAO() {
        long start = DisplayManager.getCurrentTime();
        int vaoID = GL30.glGenVertexArrays(); // The first of each frame takes ~40-200ms
        long glGen = DisplayManager.getCurrentTime();

        vaos.add(vaoID);
        long add = DisplayManager.getCurrentTime();

        GL30.glBindVertexArray(vaoID);
        long bind = DisplayManager.getCurrentTime();
        
        System.out.println(String.format("Vao: gen: %d + add: %d + bind: %d = %d", 
                (glGen-start),
                (add-glGen),
                (bind-add),
                (DisplayManager.getCurrentTime()-start)));
        return vaoID;
    }

और अंत में एक नियमित पीढ़ी में प्रिंट आउटपुट यहां दिया गया है:


NEW CHECK
NEW CHECK
Vao: gen: 7 + add: 0 + bind: 0 = 7
Vao: gen: 1 + add: 0 + bind: 0 = 1
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
NEW CHECK
Vao: gen: 209 + add: 0 + bind: 0 = 209 (why????)
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 1 + add: 0 + bind: 0 = 1
Vao: gen: 1 + add: 0 + bind: 0 = 1
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 1 = 1
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
NEW CHECK
Vao: gen: 4 + add: 0 + bind: 0 = 4
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
NEW CHECK
NEW CHECK

प्रत्येक फ्रेम मैं "नई जांच" प्रिंट कर रहा हूं और जैसा कि आप देख सकते हैं कि यह प्रत्येक फ्रेम का बिल्कुल पहला नहीं है, कभी-कभी ऐसा नहीं होता है, लेकिन जब कोई पीढ़ी की घटना होती है तो पहला हमेशा बहुत धीमा होता है।

मेरा प्रश्न यह है कि यहाँ क्या हो रहा है और मैं क्या कर सकता/सकती हूँ/परीक्षण/अपडेट कर सकता हूँ?

आपकी सहायता के लिए धन्यवाद।

संपादित करें

मुझे सटीक होना चाहिए कि GL30.glGenVertexArrays() को मुख्य धागे में बुलाया जाता है। कार्यक्रम की शुरुआत में किसी और चीज से पहले निष्पादित संदर्भ कोड यहां दिया गया है:


ContextAttribs attribs = new ContextAttribs(3,2)
        .withForwardCompatible(true)
        .withProfileCore(true);
        Mouse.setGrabbed(true);

        try {
            DisplayMode displayMode = new DisplayMode(WIDTH, HEIGHT);
            Display.setDisplayMode(displayMode);
            Display.create(new PixelFormat(),attribs);
            Display.setTitle("CubeLand");
        } catch (LWJGLException e) {
            e.printStackTrace();
        }

2 संपादित करें

मैंने मुख्य धागे में सब कुछ करके मल्टीथ्रेडिंग को हटा दिया, और लगभग उसी फ्रीज को उत्पन्न करते समय होता है, जो सामान्य है क्योंकि गणना बहुत बड़ी है, लेकिन GL30.glGenVertexArrays() में कोई समय नहीं लग रहा है गणना करना। इससे सिद्ध होता है कि यह विधि अन्य सभी धागों के समाप्त होने का इंतज़ार कर रही है, लेकिन इससे क्यों और कैसे बचा जाए??


NEW CHECK
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
NEW CHECK

3 संपादित करें कुछ खबरें, जब मैं अपने लैपटॉप को अनप्लग करता हूं, तो ग्राफिक कार्ड बंद हो जाता है और मदरबोर्ड ग्राफिक चिपसेट इसे बदल देता है। अचानक मामला खत्म हो गया है। बेशक मेरे पास अभी भी फ्रीज है क्योंकि अब जब मेरा प्रदर्शन कट गया है, तो प्रोसेसर मल्टीथ्रेडिंग के साथ भी इलाके को उत्पन्न करने के लिए संघर्ष करता है, लेकिन वाओ जेन समय 0 पर वापस आ गया है। यह भ्रमित करने वाला है।

0
Thibault Abry 12 सितंबर 2020, 19:04

1 उत्तर

सबसे बढ़िया उत्तर

ठीक है, तो इसके साथ संघर्ष करने के 2 सप्ताह बाद, मुझे आखिरकार एक समाधान मिला। एक लंबे प्रोफाइलिंग सत्र के बाद, मुझे 90% यकीन है कि glGenVertexArrays() अपने कार्यों को पूरा करने के लिए कुछ थ्रेड्स की प्रतीक्षा कर रहा है, मुझे नहीं पता क्यों, लेकिन यह 2/3 बार सहसंबंधित है। वर्कअराउंड सभी वायदा के बाहर आने की प्रतीक्षा करना है, और फिर इलाके उत्पन्न करना है (उर्फ कॉल glGenVertexArrays ())। इस तरह, glGenVertexArrays() मुख्य धागे को नहीं रोक रहा है, और एक ही समय में दर्जनों इलाके बनाने से बचने के लिए मैं केवल 2-3 प्रति फ्रेम बना रहा हूं, जो ध्यान देने योग्य नहीं है।

0
Thibault Abry 21 सितंबर 2020, 17:11