扭转利用线程字符串线程、字符串

2023-09-11 03:57:00 作者:我的名字你的姓氏

最近,有人问我在采访中实现一个字符串反向使用功能的线程。我想出了以下解决方案的大部分。选定了与否是一个不同的故事:-)。我试图运行下面的解决方案,我家的电脑运行Windows 8消费者preVIEW上。编译器是VC11 Beta版。

的问题是,在多线程code是始终无论是作为快或比顺序code 1毫秒慢。输入我给的大小32.4 MB的文本文件。有没有一种方法,使多线程code更快?抑或是给定的输入过少什么区别?

修改

我只写了 void反转(字符*海峡,诠释求,诠释年底,INT rbegin,INT雷德); 和  无效CustomReverse(字符*海峡); 方法的采访。所有其他code被写入在家里。

 模板< typename的功能>
    无效TimeIt(功能和安培;&安培;乐趣,为const char *标题)
    {
        clock_t表示开始=时钟();
        有趣();
        用clock_t蜱=时钟() - 启动;
        性病::法院<<的std ::运输及工务局局长(30)<<标题<< :&其中;&其中; (双)蜱/ CLOCKS_PER_SEC<< \ N的;
    }

    void反转(字符*海峡)
    {


        断言(海峡!= NULL);
        的for(int i = 0,J =的strlen(STR) -  1; I< D​​]; ++我,--j)
        {
            如果(STR [I]!=海峡[J]。)
            {
                的std ::交换(STR [我],海峡[J]);
            }
        }

    }

     void反转(字符*海峡,诠释求,诠释年底,INT rbegin,INT雷德)
        {
            对于(;求< =结束和放大器;&安培; rbegin> =雷德++初学者,--rbegin)
            {
                如果(STR [求]!=海峡[rbegin])
                {
                    焦炭TEMP =海峡[求]
                    海峡[求] = STR [rbegin]
                    海峡[rbegin] =气温;
                }
            }
        }

        无效CustomReverse(字符*海峡)
        {
            INT LEN =的strlen(海峡);
            const int的max_threads的=的std ::螺纹:: hardware_concurrency();
            的std ::矢量<的std ::线程>螺纹;

            threads.reserve(max_threads的);

            const int的CHUNK = LEN / max_threads的> (4096)? (4096):LEN / max_threads的;

            / *性病::法院<< LEN:<< LEN<< \ N的;
            性病::法院<< max_threads的:&其中;&其中; max_threads的<< \ N的;
            性病::法院<< CHUNK:<< CHUNK<< \ N; * /

        的for(int i = 0,J = LEN  -  1; I< D​​];)
                {
                    如果第(i + CHUNK&其中; J&安培;&安培;的J  -  CHUNK I标记)
                    {
                        为(中间体K = 0; K&其中; max_threads的&安培;及(1 +&CHUNK其中; J&安培;&安培;的J  -  CHUNK I标记); ++ k)的
                        {
                             threads.push_back(STD ::线程([=,&安培; STR(){反转(海峡,我,
                                                    1 + CHUNK,J,J  - 分块); }));
                            I + = CHUNK + 1;
                            的J  -  = CHUNK + 1;
                        }


                        为(自动&安培;日:螺纹)
                        {
                            th.join();
                        }

                        threads.clear();
                    }
                    其他
                    {
                                        焦炭TEMP =海峡[I]
                                        海峡[i] = STR [J]。
                                        海峡[J] = STR [I]
                        我++;
                        j--;
                    }
                }
            }


        无效写(的std :: ostream的&放大器;&放大器; OS,常量标准::字符串&安培; STR)
        {
           OS<<海峡<< \ N的;
        }

        无效CustomReverseDemo(INT ARGC,字符** argv的)
        {
            性病:: ifstream的inpfile;
            的for(int i = 0; I< ARGC; ++ I)
                性病::法院<<的argv [1]  - ;&其中; \ N的;

            inpfile.open(的argv [1],标准::内部监督办公室::中);

            的std :: ostringstream OSS;
            性病::串线;

            如果(!inpfile.is_open())
            {
                返回;
            }
            而(STD ::函数getline(inpfile,线))
            {
                OSS<<线;
            }

            标准::字符串序列(oss.str());
            标准::字符串面值(oss.str());

            性病::法院<< 现在倒车的\ n;

            TimeIt([安培] {CustomReverse(安培;票面[0]);},使用并行code \ N);
            TimeIt([安培] {反向(放大器;序列[0]);},使用顺序code \ N);
            TimeIt([安培] {反向(放大器;序列[0]);},使用顺序code \ N);
            TimeIt([安培] {CustomReverse(安培;票面[0]);},使用并行code \ N);



            写(标准::的ofstream(sequential.txt),SEQ);
            写(标准::的ofstream(Parallel.txt),标准杆);
        }

        INT主(INT ARGC,字符* argv的[])
        {
            CustomReverseDemo(ARGC,ARGV);
        }
 

解决方案

我试着写有相同的功能的程序: 我的冲销努力使用线程字符串

我已经测试了与VC11 Beta版和MinGW(GCC 4.8)在Windows 7

2核处理器

测试结果:

VC11 Beta版:

7 MB 文件:

调试

简单的反向:0.468

异步反向:0.275

发布

简单的反向:0.006

异步反向:0.014

98 MB 文件:

调试

简单的反向:5.982

异步反向:3.091

发布

简单的反向:0.063

异步反向:0.079

782 MB 文件

发布

简单的反向:0.567

异步反向:0.689

称为Mingw:

782 MB 文件

发布

简单的反向:0.583

异步反向:0.566

正如你所看到的多线程code胜仅在调试版本。但在发布编译器可以优化并使用所有内核即使在单线程code。

那么信任你的编译器=)

窥探现代浏览器架构 二

Recently, I was asked in a interview to implement a string reverse function using threads. I came up with most part of the solution below. Got selected or not is a different story :-). I tried to run the below solution on my home PC running Windows 8 consumer preview. The compiler is VC11 Beta.

The question is, the multi-threaded code is always either as fast or 1 millisecond slower than the sequential code. The input I gave is a text file of size 32.4 MB. Is there a way to make the multi-threaded code faster ? Or is it that the input given is too less to make any difference ?

EDIT

I only wrote void Reverse(char* str, int beg, int end, int rbegin, int rend); and void CustomReverse(char* str); methods in the interview. All the other code is written at home.

 template<typename Function>
    void TimeIt(Function&& fun, const char* caption)
    {
        clock_t start = clock();     
        fun();     
        clock_t ticks = clock()-start;     
        std::cout << std::setw(30) << caption          << ": "          << (double)ticks/CLOCKS_PER_SEC << "\n"; 
    }

    void Reverse(char* str)
    {


        assert(str != NULL);
        for ( int i = 0, j = strlen(str) - 1; i < j; ++i, --j)
        {
            if ( str[i] != str[j])
            {
                std::swap(str[i], str[j]);
            }
        }

    }

     void Reverse(char* str, int beg, int end, int rbegin, int rend)
        {
            for ( ; beg <= end && rbegin >= rend; ++beg, --rbegin)
            {
                if ( str[beg] != str[rbegin])
                {
                    char temp = str[beg];
                    str[beg] = str[rbegin];
                    str[rbegin] = temp;
                }
            }
        }

        void CustomReverse(char* str)
        {
            int len = strlen(str);
            const int MAX_THREADS = std::thread::hardware_concurrency();
            std::vector<std::thread> threads;

            threads.reserve(MAX_THREADS);

            const int CHUNK = len / MAX_THREADS > (4096) ? (4096) : len / MAX_THREADS;

            /*std::cout << "len:" << len << "\n";
            std::cout << "MAX_THREADS:" << MAX_THREADS << "\n";
            std::cout << "CHUNK:" << CHUNK << "\n";*/

        for ( int i = 0, j = len - 1; i < j; )
                {
                    if (i + CHUNK < j && j - CHUNK > i )
                    {
                        for ( int k = 0; k < MAX_THREADS && (i + CHUNK < j && j - CHUNK > i ); ++k)
                        {                                                
                             threads.push_back( std::thread([=, &str]() { Reverse(str, i,    
                                                    i + CHUNK, j, j - CHUNK); }));
                            i += CHUNK + 1;
                            j -= CHUNK + 1;
                        }


                        for ( auto& th : threads)
                        {
                            th.join();
                        }

                        threads.clear();
                    }
                    else
                    {          
                                        char temp = str[i];
                                        str[i] = str[j];
                                        str[j] = str[i];
                        i++;
                        j--;
                    }
                }
            }


        void Write(std::ostream&& os, const std::string& str)
        {
           os << str << "\n";
        }

        void CustomReverseDemo(int argc, char** argv)
        {
            std::ifstream inpfile;
            for ( int i = 0; i < argc; ++i)
                std::cout << argv[i] << "\n";

            inpfile.open(argv[1], std::ios::in);

            std::ostringstream oss;
            std::string line;

            if (! inpfile.is_open())
            {
                return;
            }
            while (std::getline(inpfile, line))
            {
                oss << line;
            }

            std::string seq(oss.str());
            std::string par(oss.str());

            std::cout << "Reversing now\n";

            TimeIt( [&] { CustomReverse(&par[0]); }, "Using parallel code\n");  
            TimeIt( [&] { Reverse(&seq[0]) ;}, "Using Sequential Code\n");
            TimeIt( [&] { Reverse(&seq[0]) ;}, "Using Sequential Code\n");
            TimeIt( [&] { CustomReverse(&par[0]); }, "Using parallel code\n");      



            Write(std::ofstream("sequential.txt"), seq);
            Write(std::ofstream("Parallel.txt"), par);
        }

        int main(int argc, char* argv[])
        {
            CustomReverseDemo(argc, argv);
        }

解决方案

I tried to write the program with same functionality: My effort of "Reversing a string using threads"

I have tested that with 2 core processor with VC11 Beta and mingw(gcc 4.8) on Windows 7

Testing results:

VC11 Beta:

7 Mb file:

Debug

Simple reverse: 0.468

Async reverse : 0.275

Release

Simple reverse: 0.006

Async reverse : 0.014

98 Mb file:

Debug

Simple reverse: 5.982

Async reverse : 3.091

Release

Simple reverse: 0.063

Async reverse : 0.079

782 Mb file

Release

Simple reverse: 0.567

Async reverse : 0.689

Mingw:

782 Mb file

Release

Simple reverse: 0.583

Async reverse : 0.566

As you can see multi-threaded code wins only in debug build. But in release compiler makes optimization and uses all cores even in case of single-threaded code.

So trust your compiler =)