我想用自己的优化版本替换memcpy来做一些基准测试。 我不想修改调用memcpy的代码中的每个地方(这是一个很大的代码库,我想避免很多更改)。所以我做的是以下内容:
// in a "common" header file which is included everywhere
#ifdef SHOULD_OPTIMIZE
#define memcpy my_on_steroids_memcpy
#endif
以上工作并将memcpy替换为我自己的实现,但它看起来很粗糙,强制而且根本不安全。是否有任何其他选择,以便我可以替换库memcpy而不修改其余的代码?我是否应该忘记上述内容,因为它似乎不是一个值得建议的事情,只是修改所有其他文件(以及为什么)?
答案 0 :(得分:2)
某些编译器可以从命令行中包含标头。例如,可以使用g++
选项调用gcc
和-include
。
但是,我确定你的代码至少在没有自定义标头的情况下进行编译和运行,因为如果没有“神秘”编译器标志,你的代码会被认为是“不礼貌”。
另外:memcpy的标准库实现通常已经 优化了SSE2优化等。你可能无法做得更好。
答案 1 :(得分:1)
我将假设您正在运行Linux ...
附加链接是关于如何使用LD_PRELOAD替换应用程序中现有函数的示例。该示例采用普通的malloc调用,然后确保内存已被清零。如何将其翻译成memcpy应该是相当明显的。
答案 2 :(得分:1)
如果您使用的是Linux,那么memcpy已经非常优化,可能甚至更多(我认为我们注意到在页面边框上使用memcpy会发生一次崩溃)。
也就是说,您完全可以在程序中定义替换memcpy
。它将被调用而不是C库。你不必做任何其他事情。
答案 3 :(得分:1)
我刚刚找到了另一种替换memcpy
函数调用的方法。它只适用于GCC(我仍然需要为VC ++找到另一种方法),但我认为它肯定比原始#define
方式更好。它使用__REDIRECT
宏(在sys/cdefs.h
中包含的features.h
),这是我在glibc中广泛使用的内容。下面是一个小测试的例子:
// modified.h
#pragma once
#ifndef MODIF_H_INCLUDED_
#define MODIF_H_INCLUDED_
#include <cstddef>
#include <features.h>
extern "C"
{
void test_memcpy(void* __restrict to, const void* __restrict from, size_t size);
}
#if defined(__GNUC__)
void __REDIRECT(memcpy, (void* __restrict to, const void* __restrict from, size_t size),
test_memcpy);
#endif /* __GNUC__ */
#endif /* MODIF_H_INCLUDED_ */
//modified.cpp
extern "C" void test_memcpy(void* __restrict to, const void* __restrict from,
size_t size)
{
std::cout << "Dumb memcpy replacement!\n";
}
//original.h
#pragma once
#ifndef ORIG_H_INCLUDED_
#define ORIG_H_INCLUDED_
void test_with_orig();
#endif /* ORIG_H_INCLUDED_ */
//original.cpp
#include <cstring>
#include <iostream>
void test_with_orig()
{
int* testDest = new int[10];
int* testSrc = new int[10];
for (unsigned int i = 0; i < 10; ++i)
{
testSrc[i] = i;
}
memcpy(testDest, testSrc, 10 * sizeof(int));
for (unsigned int i = 0; i < 10; ++i)
{
std::cout << std::hex << "\nAfter standard memcpy - "
<< "Source: " << testSrc[i] << "\tDest: " << testDest[i] << "\n";
}
}
// and a small test
#include "modified.h"
#include "original.h"
#include <iostream>
#include <cstring>
int main()
{
int* testDest = new int[10];
int* testSrc = new int[10];
for (unsigned int i = 0; i < 10; ++i)
{
testSrc[i] = i;
testDest[i] = 0xDEADBEEF;
}
memcpy(testDest, testSrc, 10 * sizeof(int));
for (unsigned int i = 0; i < 10; ++i)
{
std::cout << std::hex << "\nAfter memcpy replacement - "
<< "Source: " << testSrc[i] << "\tDest: " << testDest[i] << "\n";
}
test_with_orig();
return 0;
}
答案 4 :(得分:0)
如果您不想更改现有代码,这似乎是唯一可用的解决方案;并且它不应该太糟糕,因为如果您自己的memcpy的签名与默认签名不匹配,编译器会抱怨。
那就是说,我会怀疑你是否能够比标准库附带的memcpy挤出更好的性能。但是,你是否正在复制那些成为问题的记忆?