2012-07-24 17 views
8

मुझे पता है कि जावा एक सुरक्षित भाषा है लेकिन जब मैट्रिक्स की गणना की आवश्यकता होती है, तो क्या मैं कुछ तेज़ी से कोशिश कर सकता हूं?जावा इंजेक्शन/जावा में असेंबली कोडिंग?

मैं सी ++, डिजिटल-मंगल कंपाइलर और एफएएसएम में __asm ​​{} सीख रहा हूं। मैं जावा में ऐसा करना चाहता हूं। मैं कार्यों में असेंबली कोड कैसे रेखांकित कर सकता हूं? क्या यह भी संभव है?

कुछ इस तरह (एक vectorized पाश शाखाओं में बिना एक मूल्य के एक सरणी के सभी तत्वों को कड़ाई से बंद करना, सीपीयू की AVX समर्थन का उपयोग कर):

JavaAsmBlock(
    # get pointers into registers somehow 
    # and tell Java which registers the asm clobbers somehow 
    vbroadcastss twenty_five(%rip), %ymm0 
    xor %edx,%edx 
.Lloop:       # do { 
    vmovups (%rsi, %rdx, 4), %ymm1 
    vcmpltps %ymm1, %ymm0, %ymm2 
    vblendvps %ymm2, %ymm0, %ymm1, %ymm1 
    vmovups %ymm1, (%rdi, %rdx, 4) 
    # TODO: unroll the loop a bit, and maybe use aligned loads/stores in the main loop 
    add   $32, %rdx 
    cmp   %rcx, %rdx 
    jb  .Lloop     # } while(idx < count) 
); 

System.out.println(var[0]); 

मैं एक कोड-इंजेक्टर का उपयोग नहीं करना चाहते हैं। मैं इंटेल या AT & टी शैली x86 निर्देश देखना चाहता हूं।

+0

आप ऐसा एएसएम लेखन (16-बिट रजिस्टर और 'div' बजाय एक' SHR अल के 4 से उपयोग करते हुए, 2'), [यह निश्चित रूप से है कर रहे हैं * नहीं * तेजी से क्या एक सी संकलक कर सकता होने जा रहा आप के लिए बनाते हैं।] (https://stackoverflow.com/questions/40354978/why-is-this-c-code-faster-than-my-hand-written-assembly-for-testing-the-collat/40355466# 40355466), तो आपको सी या सी ++ के साथ जेएनआई का उपयोग करना चाहिए। एएसएम केवल प्रदर्शन के लिए उपयोगी है यदि आप जानते हैं कि वर्तमान CPUs के माइक्रोआर्किटेक्चर के लिए कैसे ट्यून करें। यह एक उपयोगी सवाल है, लेकिन उदाहरण एक उदाहरण है कि अधिकांश लोगों को * एएसएम का उपयोग क्यों नहीं करना चाहिए। –

+0

आप सही हैं। एक ही समय में दो चीजें। यदि मैं उस समय पर्याप्त अनुभव था तो मैं निर्देशों के उचित क्रम के साथ एक एवीएक्स डॉट उत्पाद की तरह कुछ जोड़ूंगा। –

+0

आप कुछ आधुनिक उपयोग करने के लिए प्रश्न को संपादित कर सकते हैं। शायद बीएमआई 2 'पीडीएपी' की तरह, जिसमें जावा अंतर्निहित नहीं है। आदर्श रूप में आप कुछ ऐसी चीज के साथ आ सकते हैं जो आप आसानी से सी संकलक को आपके लिए उत्सर्जित नहीं कर सके। –

उत्तर

13

आपके जावा कोड और अंतर्निहित हार्डवेयर के बीच अमूर्तता की एक परत है जो इस तरह की चीज को सिद्धांत रूप में असंभव बनाती है; आप तकनीकी रूप से यह नहीं जानते कि अंतर्निहित मशीन पर आपका कोड किस प्रकार प्रदर्शित होता है, क्योंकि उसी बाइटकोड विभिन्न प्रोसेसर और विभिन्न आर्किटेक्चर पर चल सकता है।

आप आधिकारिक तौर पर कर सकते हैं Java Native Interface (जेएनआई) का उपयोग अपने जावा कोड से देशी कोड को कॉल करने के लिए करें। कॉल ओवरहेड पर्याप्त है, और जावा के साथ डेटा साझा करना काफी महंगा है, इसलिए इसका उपयोग मूल कोड के सभ्य आकार के हिस्सों के लिए किया जाना चाहिए।

सिद्धांत रूप में, ऐसा एक्सटेंशन संभव होना चाहिए, हालांकि। कोई एक जावा कंपाइलर की कल्पना कर सकता है जिसने एक विशिष्ट प्लेटफॉर्म को लक्षित किया है और असेंबली से बच निकला है। कंपाइलर को अपनी एबीआई प्रकाशित करना होगा, इसलिए आप कॉलिंग सम्मेलनों को जान लेंगे। हालांकि, मुझे ऐसा करने की कोई जानकारी नहीं है। लेकिन severalcompilersavailable हैं जो जावा को सीधे देशी कोड में संकलित करते हैं; यह संभव है कि उनमें से कोई मेरी जानकारी के बिना ऐसा कुछ समर्थन करता है, या ऐसा करने के लिए बढ़ाया जा सकता है।

अंत में, कुल मिलाकर एक अलग स्तर पर, वहाँ JVM के लिए बाईटकोड अस्सेम्ब्लेर्स हैं, Jasmin. की तरह एक बाईटकोड कोडांतरक आप "मशीन कोड" कि JVM सीधे लक्षित करता है लिखते हैं, और कभी कभी तुम javac संकलक की तुलना में बेहतर कोड लिख सकते हैं देता है सकते हैं उत्पन्न करते हैं। किसी भी घटना में, खेलना मजेदार है।

+0

ठीक है। By बाइटकोड असेंबलर को भी –

+2

उपलब्ध देशी जावा कंपाइलर्स के लिए उपलब्ध समय के समय में, [एक्सेलसियर जेट] (http://www.excelsiorjet.com) केवल जेएनआई लागू करता है, जबकि [जीसीजे] (http: // gcc .gnu.org/जावा /) जेएनआई और इसके स्वयं के इंटरफ़ेस का भी समर्थन करता है जिसे [सीएनआई] (http://gcc.gnu.org/onlinedocs/gcj/About-CNI.html) कहा जाता है। –

2

आप सीधे जावा से असेंबली नहीं कॉल कर सकते हैं। लेकिन आप JNI के माध्यम से सी कोड को कॉल कर सकते हैं, और वहां से आप असेंबली कॉल कर सकते हैं।

This article shows how.

+0

बहुत अच्छा है। मैं कोशिश करूँगा। मैं डिजिटल मर्स कंपाइलर का उपयोग कर रहा हूँ। क्या आपको लगता है कि यह __asm ​​के साथ संभव है? एनवीएम मैं खुद कोशिश करूँगा। जहां तक ​​मुझे याद है, –

+0

धन्यवाद, आप जो भी सी संकलक आपको पसंद कर सकते हैं उसका उपयोग कर सकते हैं। जावा बस मंच एबीआई का उपयोग करता है। –

+0

आप सी एबीआई के बाद असेंबली में एक फ़ंक्शन लिख सकते हैं, और इस प्रकार इसे सी फ़ंक्शन के समान कहा जा सकता है। असल में, जो भी आप सीएन फ़ंक्शन में जेएनआई संगत बनाने के लिए करेंगे, आप एएसएम में कर सकते हैं। –

1

आप JNI या JNA का उपयोग करें और जावा से अपनी मूल कार्यों कहते हैं। या एक विकल्प के रूप में, आपके पास इनपुट स्ट्रीम के रूप में बाइटकोड है और इसमें से जावा क्लास बना है।

1

आप Aparapi पर भी एक नज़र डालना चाहते हैं।

+0

GPU के लिए समानांतर प्रोग्रामिंग के लिए aparapi नहीं है? –

+3

हां। क्या आपने मैट्रिक्स गणनाओं को तेज़ी से करने के लिए नहीं पूछा था? –

2

Machine Level Java तकनीक का उपयोग कर जावा से असेंबली कॉल करना संभव है। यह जावा में लिखे गए आपके असेंबली कोड को पारदर्शी रूप से पैक करता है, लेकिन मूल पुस्तकालय में सबसे अधिक उपयोग किए जाने वाले असेंबली सिंटैक्स के समान होता है। और इसके बाद आपको केवल एक मूल विधि को कॉल करने की आवश्यकता है, जिसे आप उसी कक्षा में परिभाषित करते हैं, जहां आपकी असेंबली लिखी जाती है। इसलिए, आप हमेशा जावा पर्यावरण के भीतर रहते हैं और जावा आईडीई से कुछ असेंबली टूल्स में स्विच करने की आवश्यकता नहीं है और फिर जावा पर वापस जाने की आवश्यकता नहीं है।

+0

ऐसा लगता है कि आप जिस एपीआई को दस्तावेज की कमी का सुझाव दे रहे हैं। क्या आप अधिक जानकारी प्रदान कर सकते हैं? –

+0

जेनी की तुलना में कम एपीआई/इंटरफेस विलंबता? –

5

आप सीधे अपने जावा कोड में असेंबली को रेखांकित नहीं कर सकते हैं। फिर भी, कुछ अन्य उत्तरों द्वारा दावा किया गया है कि किसी भी मध्यस्थ सी (या सी ++) परत के बिना आसानी से असेंबली कॉलिंग संभव है।

पूर्वाभ्यास

पर विचार करें निम्नलिखित जावा वर्ग:

public class MyJNIClass { 

    public native void printVersion(); 

} 

मुख्य विचार एक प्रतीक JNI नामकरण परंपरा का उपयोग करके घोषित करने के लिए है। इस मामले में, आपके असेंबली कोड में उपयोग किए जाने वाले उलझन वाले नाम Java_MyJNIClass_printVersion हैं। यह प्रतीक अन्य अनुवाद इकाइयों, जो उदाहरण के लिए FASM में public निर्देश या एनएएसएम में global निर्देशों का उपयोग प्राप्त किया जा सकता से दिखाई देना चाहिए।

लिखें लक्षित वास्तुकला का बुला सम्मेलनों के साथ अपने विधानसभा कोड (तर्क रजिस्टरों में,,, पारित किया जा सकता अन्य स्मृति संरचनाओं में स्टैक पर आदि)। पहला तर्क अपने विधानसभा कार्य करने के लिए पारित कर दिया JNIEnv के लिए सूचक है, जो खुद JNI समारोह मेज पर एक सूचक है। जेएनआई कार्यों को कॉल करने के लिए इसका इस्तेमाल करें। उदाहरण के लिए, एनएएसएम का उपयोग करने और लक्षित करने x86_64 के लिए: JNI कार्यों के लिए

global Java_MyJNIClass_printVersion 

section .text 

Java_MyJNIClass_printVersion: 
    mov rax, [rdi] 
    call [rax + 8*4] ; pointer size in x86_64 * index of GetVersion 
    ... 

इंडेक्स Java documentation में पाया जा सकता। चूंकि जेएनआई फ़ंक्शन तालिका मूल रूप से पॉइंटर्स की एक सरणी है, इसलिए इन इंडेक्स को लक्षित आर्किटेक्चर में पॉइंटर के आकार से गुणा करना न भूलें।

दूसरा तर्क अपने विधानसभा कार्य करने के लिए पारित कर दिया बुला जावा वर्ग या वस्तु के लिए एक संदर्भ है। बाद के तर्क आपके मूल जावा विधि के पैरामीटर हैं।

अंत में, ऑब्जेक्ट फ़ाइल उत्पन्न करने के लिए अपना कोड इकट्ठा करें, और उसके बाद उस ऑब्जेक्ट फ़ाइल से साझा लाइब्रेरी बनाएं (जीसीसी gcc -shared -o ... के समान कमांड के साथ यह अंतिम चरण निष्पादित कर सकता है)।

उदाहरण चल रहा है

मैं बनाया है एक fully runnable example on GitHub, एक बार देख ले और एक बेहतर समझ पाने के लिए यह के साथ चारों ओर खेलने के लिए स्वतंत्र लग रहा है।

+0

तो यह जेएनआई सी ++ से भी गहरा है? –

+0

वैसे यह सी या सी ++ के साथ एक ही जेएनआई कार्यान्वयन का उपयोग कर रहा है, लेकिन हां, निचले स्तर से। ;-) – Pyves

+1

आप 'mov रैक्स, [आरडीआई] '/' कॉल [रैक्स + 8 * 4]' लिखा हो सकता था। x86 एड्रेसिंग मोड अतिरिक्त निर्देशों की तुलना में अधिक कुशल हैं। मेमोरी-अप्रत्यक्ष कॉल लोड + कॉल से तेज नहीं है, लेकिन यह धीमा नहीं है और कोड आकार और डीकोड बैंडविड्थ बचाता है। (हम्म, वास्तव में http://agner.org/optimize/ के मुताबिक, यह एएमडी पर धीमा हो सकता है, क्योंकि यह 2 से अधिक यूओपीएस है और इसका मतलब है वेक्टरपाथ (माइक्रोकोडेड), डायरेक्टपैथ नहीं। अगर एएमडी के लिए ट्यूनिंग हो, तो 'mov रैक्स , [आरडीआई] '/' mov रैक्स, [रैक्स + 8 * 4] '/' कॉल रैक्स '। फिर भी कोई एडीडी निर्देश नहीं है, यह हमेशा खराब होता है) –

संबंधित मुद्दे