- Sieve of Erastosthenes optimized to the max - 2 Updates
- MSVC-bug - 1 Update
wij <wyniijj5@gmail.com>: Feb 14 12:15AM +0800 On Sun, 2023-12-10 at 10:46 +0100, Bonita Montero wrote: > cpuId( 0x80000006u ); > return ((unsigned)regs[2] >> 16) * 1024; > } I just wrote a class PrimeTab to test prime numbers. It took 73s to complete. 0.1s is too unbelievable. Something must be wrong. ------------- PrimeTab.h #include <Wy.stdlib.h> #include <CSCall/VLInt.h> // Very Large Integer // [Syn] PrimeTab is a table for prime numbers // class PrimeTab { typedef uint64_t NumType; WY_ENSURE(sizeof(NumType)<=sizeof(size_t)); Wy::VLInt m_ptab; NumType m_maxn; // [Syn] Get the bit position storing info. for n // 0= pos for n (n is composite) is not available // size_t bpos(NumType n) { switch(n%6) { case 1: return 2*(n/6); case 5: return 2*(n/6)+1; default: return 0; } }; public: WY_DECL_REPLY; PrimeTab() : m_ptab(), m_maxn(0) {}; PrimeTab(const PrimeTab& s) : m_ptab(s.m_ptab), m_maxn(s.m_maxn) {}; PrimeTab(PrimeTab& s, Wy::ByMove_t) : m_ptab(s.m_ptab,Wy::ByMove), m_maxn(s.m_maxn) {}; // [Syn] Create prime table for numbers<=maxn // explicit PrimeTab(NumType maxn) : m_ptab(), m_maxn(maxn) { for(NumType n=2; n<=m_maxn; ++n) { size_t p= bpos(n); if(p==0) { continue; // composite number } if(m_ptab.bit(p)) { continue; // composite number } for(NumType m=n+n; m<=m_maxn; m+=n) { Wy::Errno r=m_ptab.set_bit(bpos(m),true); if(r!=Wy::Ok) { WY_THROW( Reply(r) ); } } }; }; NumType max_num() const { return m_maxn; }; bool is_prime(NumType n) { if(n>m_maxn) { WY_THROW( Reply(EINVAL) ); } if(n<=6) { switch(n) { case 1: // FALLTHROUGH case 2: // FALLTHROUGH case 3: // FALLTHROUGH case 5: return true; default: return false; } } size_t p= bpos(n); if(p==0) { return false; } return !m_ptab.bit(p); }; void swap(PrimeTab& ano) { m_ptab.swap(ano.m_ptab); Wy::swap(m_maxn, ano.m_maxn); }; void reset() { m_ptab.reset(); }; Wy::Errno reset(NumType maxn) try { PrimeTab tmp(maxn); Wy::swap(tmp); return Wy::Ok; } catch(const Wy::Errno& e) { WY_RETURN(e); }; Wy::Errno reset(const PrimeTab& rhs) { WY_RETURN(m_ptab.reset(rhs.m_ptab)); }; PrimeTab& operator=(const PrimeTab& rhs) { Wy::Errno r=m_ptab.reset(rhs.m_ptab); if(r!=Wy::Ok) { WY_THROW( Reply(r) ); } return *this; }; }; -------------- chk_primetab.cpp #include <Wy.stdio.h> #include "PrimeTab.h" using namespace Wy; void ck1() { size_t cnt; PrimeTab ptab(1LL<<32); cnt=0; for(size_t n=0; n<ptab.max_num(); ++n) { if(ptab.is_prime(n)) { ++cnt; // cout << n << WY_ENDL; } } cout << "cnt=" << cnt << WY_ENDL; }; int main() try { cout << "Check PrimeTab.h ..." WY_ENDL; ck1(); cout << "OK" WY_ENDL; return 0; } catch(const Errno& e) { cerr << wrd(e) << WY_ENDL; return -1; } catch(...) { cerr << "main caught(...)" WY_ENDL; return -1; }; ------------- []$ g++ chk_primetab.cpp -lwy -O2 []$ time ./a.out Check PrimeTab.h ... cnt=203280222 OK real 1m13.716s user 1m13.180s sys 0m0.168s |
Bonita Montero <Bonita.Montero@gmail.com>: Feb 13 07:08PM +0100 Am 13.02.2024 um 17:15 schrieb wij: > I just wrote a class PrimeTab to test prime numbers. It took 73s to > complete. > 0.1s is too unbelievable. Something must be wrong. There's nothing wrong with that. I'm storing the bits as a bitmap and I'm using a segmented sieve and I partition the part beyond the square root in chunks which are according to the logical number of CPUs and these are further divided into chunks which fit into the L2-cache. And the sequential lookup inside the bitmap below the square root is done with countl_zero, which maps to a single CPU-instruction on most computers. The naive single-threeaded approach without cache-partititioning is for sure magnitudes slower. |
Bonita Montero <Bonita.Montero@gmail.com>: Feb 13 12:07PM +0100 If you initialize a function<>-object with a reference_wrapper it is guaranteed that the function<>-object references an external function-object without any memory allocation. libstdc++ and libc++ don't allocate any memory with such function<>-objects according to the standard, but MSVC does allocate external memory. #include <iostream> #include <functional> using namespace std; void *operator new( size_t n ) { cout << "alloc" << endl; void *p = malloc( n ); if( !p ) throw bad_alloc(); return p; } void operator delete( void *p ) { free( p ); } int main() { function<void ()> fn; string str( "hello word" ); auto lam = [str = str]() { cout << str << endl; }; fn = ref( lam ); fn(); } |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment