পাইথনে আপনার অনুরোধকৃত ভাষায় এর উত্তর দেওয়ার পক্ষে যথেষ্ট জ্ঞানহীন নয়, তবে সি / সি ++ এ আপনার প্রশ্নের প্যারামিটারগুলি দিয়ে আমি শূন্যগুলি এবং বিটগুলিকে রূপান্তরিত করে একটি uint64_t এর ন্যূনতম উল্লেখযোগ্য বিটগুলিতে ঠেলাচ্ছি push এটি আপনাকে এক ঝরনা - 1 ঘড়ির মধ্যে 55 টি বিটের তুলনা করতে দেয়।
দুর্ভাগ্যক্রমে দ্রুত এবং পুরো জিনিস অন চিপ ক্যাশে (209,880 বাইট) ফিট করবে। একই সাথে সমস্ত 55 তালিকা সদস্যকে স্থানান্তরিত করার জন্য হার্ডওয়্যার সমর্থন কেবলমাত্র সিপিইউ'র রেজিস্টারে উপলব্ধ। একই সাথে সমস্ত 55 সদস্যের তুলনা করা যায়। এটি সফ্টওয়্যার সমাধানে সমস্যার 1-for-1 ম্যাপিংয়ের অনুমতি দেয়। (এবং সিমডি / এসএসই 256 বিট রেজিস্টারগুলি ব্যবহার করা প্রয়োজন, 256 জন সদস্য প্রয়োজন হলে) ফলস্বরূপ কোডটি তাত্ক্ষণিকভাবে পাঠকের কাছে সুস্পষ্ট।
আপনি পাইথনে এটি বাস্তবায়ন করতে সক্ষম হতে পারেন, আমি এটি যথেষ্ট জানি না এটি সম্ভব কিনা বা পারফরম্যান্স কী হতে পারে তা জানার জন্য।
এটির পরে ঘুমানোর পরে কয়েকটি বিষয় সুস্পষ্ট হয়ে উঠল এবং সর্বোপরি ভাল।
1.) বিটগুলি ব্যবহার করে বিজ্ঞপ্তিযুক্ত লিঙ্কযুক্ত তালিকাকে স্পিন করা এত সহজ যে ডালির খুব চালাক কৌশলটি প্রয়োজনীয় নয়। একটি 64৪-বিট রেজিস্ট্রারের অভ্যন্তরে স্ট্যান্ডার্ড বিট শিফটিংটি খুব সহজেই আবর্তনটি সম্পন্ন করবে এবং বিট অপ্সের পরিবর্তে পাটিগণিত ব্যবহার করে আরও সমস্ত পাইথনকে বন্ধুত্বপূর্ণ করার প্রয়াসে।
২) বিট শিফটিংটি 2 দ্বারা ভাগ করে সহজেই সম্পাদন করা যায়।
৩) তালিকার শেষে 0 বা 1 এর জন্য চেক করা খুব সহজে মডুলো 2 দ্বারা করা যেতে পারে।
৪) লেজ থেকে তালিকার শীর্ষে a 0 এ "সরানো" ২ দ্বারা ভাগ করে করা যায় can এটি কারণ যদি শূন্যটি সরানো থাকে তবে এটি 55 তম বিটকে মিথ্যা করে দেবে, এটি ইতিমধ্যে সম্পূর্ণরূপে কিছুই না করে।
৫) লেজ থেকে তালিকার শীর্ষে "1" এ 1 মুভিং 2 দ্বারা ভাগ করে 18,014,398,509,481,984 যোগ করে করা যায় - যা 55 তম বিট সত্য এবং বাকীটি মিথ্যা চিহ্নিত করে তৈরি করা মান।
)) যদি কোনও অ্যাঙ্কর এবং রচনাযুক্ত uint64_t এর তুলনা যদি কোনও প্রদত্ত ঘোরাঘুরির পরে সত্য হয় তবে বিরতি দিন এবং সত্য প্রত্যাবর্তন করুন।
বার বার রূপান্তর না করতে এড়াতে আমি তালিকার পুরো অ্যারেটিকে সরাসরি uint64_ts এর অ্যারে রূপান্তর করব।
কোডটি অপ্টিমাইজ করার চেষ্টা করে কয়েক ঘন্টা ব্যয় করার পরে, এসেম্বলির ভাষা অধ্যয়ন করে আমি রানটাইম থেকে 20% শেভ করতে সক্ষম হয়েছি। আমার যুক্ত করা উচিত যে ও / এস এবং এমএসভিসি সংকলক গতকাল মধ্য-দিন আপডেট হয়েছিল। যে কোনও কারণেই হোক না কেন, সি সংকলক উত্পাদিত কোডের মান আপডেটের পরে (11/15/2014) নাটকীয়ভাবে উন্নত হয়েছিল। রান-টাইম এখন ~ 70 টি ঘড়ি, একটি পরীক্ষার রিংয়ের 55 টি টার্নের সাথে একটি অ্যাঙ্কর রিংটি রচনা এবং তুলনা করতে 17 ন্যানোসেকেন্ড এবং অন্য সকলের বিপরীতে সমস্ত রিংয়ের এনএক্সএন 12.5 সেকেন্ডে সম্পন্ন হয় ।
এই কোডটি এতই কঠোর তবে 4 টি রেজিস্ট্রার 99% সময় কিছু না করে বসে আছেন sitting সমাবেশ ভাষা লাইন জন্য প্রায় লাইন সি কোড মেলে। পড়তে ও বুঝতে খুব সহজ। একটি দুর্দান্ত সমাবেশ প্রকল্প যদি কেউ নিজেরাই তা শিখিয়ে থাকেন।
হার্ডওয়্যার হ্যাজওয়েল আই 7, এমএসভিসি 64-বিট, সম্পূর্ণ অপ্টিমাইজেশন।
#include "stdafx.h"
#include "stdafx.h"
#include <string>
#include <memory>
#include <stdio.h>
#include <time.h>
const uint8_t LIST_LENGTH = 55; // uint_8 supports full witdth of SIMD and AVX2
// max left shifts is 32, so must use right shifts to create head_bit
const uint64_t head_bit = (0x8000000000000000 >> (64 - LIST_LENGTH));
const uint64_t CPU_FREQ = 3840000000; // turbo-mode clock freq of my i7 chip
const uint64_t LOOP_KNT = 688275225; // 26235^2 // 1000000000;
// ----------------------------------------------------------------------------
__inline uint8_t is_circular_identical(const uint64_t anchor_ring, uint64_t test_ring)
{
// By trial and error, try to synch 2 circular lists by holding one constant
// and turning the other 0 to LIST_LENGTH positions. Return compare count.
// Return the number of tries which aligned the circularly identical rings,
// where any non-zero value is treated as a bool TRUE. Return a zero/FALSE,
// if all tries failed to find a sequence match.
// If anchor_ring and test_ring are equal to start with, return one.
for (uint8_t i = LIST_LENGTH; i; i--)
{
// This function could be made bool, returning TRUE or FALSE, but
// as a debugging tool, knowing the try_knt that got a match is nice.
if (anchor_ring == test_ring) { // test all 55 list members simultaneously
return (LIST_LENGTH +1) - i;
}
if (test_ring % 2) { // ring's tail is 1 ?
test_ring /= 2; // right-shift 1 bit
// if the ring tail was 1, set head to 1 to simulate wrapping
test_ring += head_bit;
} else { // ring's tail must be 0
test_ring /= 2; // right-shift 1 bit
// if the ring tail was 0, doing nothing leaves head a 0
}
}
// if we got here, they can't be circularly identical
return 0;
}
// ----------------------------------------------------------------------------
int main(void) {
time_t start = clock();
uint64_t anchor, test_ring, i, milliseconds;
uint8_t try_knt;
anchor = 31525197391593472; // bits 55,54,53 set true, all others false
// Anchor right-shifted LIST_LENGTH/2 represents the average search turns
test_ring = anchor >> (1 + (LIST_LENGTH / 2)); // 117440512;
printf("\n\nRunning benchmarks for %llu loops.", LOOP_KNT);
start = clock();
for (i = LOOP_KNT; i; i--) {
try_knt = is_circular_identical(anchor, test_ring);
// The shifting of test_ring below is a test fixture to prevent the
// optimizer from optimizing the loop away and returning instantly
if (i % 2) {
test_ring /= 2;
} else {
test_ring *= 2;
}
}
milliseconds = (uint64_t)(clock() - start);
printf("\nET for is_circular_identical was %f milliseconds."
"\n\tLast try_knt was %u for test_ring list %llu",
(double)milliseconds, try_knt, test_ring);
printf("\nConsuming %7.1f clocks per list.\n",
(double)((milliseconds * (CPU_FREQ / 1000)) / (uint64_t)LOOP_KNT));
getchar();
return 0;
}